UIView animation duration - ios

I have an UIView and I want to change it's background color. That works well using the UIView beginAnimation:context: method. However, the animation 'lasts' for like 1 second or so. I want it to last 5 seconds. This is the code I'm using:
- (void)updateSky:(NSString *)time {
[UIView beginAnimations: #"backgroundUpdate" context:nil];
[UIView setAnimationDuration: 5.0];
gradient.colors = [NSArray arrayWithObjects: (id)[[UIColor colorWithRed:0x63/255.0f green:0xA9/255.0f blue:0xFF/255.0f alpha:1.0] CGColor],
(id)[[UIColor colorWithRed:0x8C/255.0f green:0xBF/255.0f blue:0xFF/255.0f alpha:1.0] CGColor], nil];
if(time == #"night") {
gradient.colors = [NSArray arrayWithObjects: (id)[[UIColor colorWithRed:0x1E/255.0f green:0x1E/255.0f blue:0x1E/255.0f alpha:1.0] CGColor],
(id)[[UIColor colorWithRed:0x2C/255.0f green:0x4C/255.0f blue:0x72/255.0f alpha:1.0] CGColor], nil];
}
[UIView commitAnimations];
}
gradient is defined as follows:
CAGradientLayer *gradient;
Am I doing something wrong?

The way to animate setting a UIView's background color using view animation is to set its backgroundColor property. You don't seem to be doing that. What is this thing gradient and what is its colors property? The problem here seems to be that you're using UIView animation, but colors is not a UIView animatable property so this makes no sense. You need to provide more code to show what you're really doing. For example, if this is an implicit layer animation you'd use +[CATransaction setAnimationDuration:] to set the duration.
(Also this whole beginAnimations / commitAnimations structure, while not exactly deprecated, is virtually on the chopping block. That's irrelevant to your question, but it would be good to get out of it if you can, just on principle. You should be using animateWithDuration:delay:options:animations:completion:, or implicit layer animation, or explicit Core Animation.)

Related

How to remove CAGradientLayer from UIButton when it's highlighted

I've added gradient effect for my Button and added it as a sub layer to my Button.
Code is :
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.myButton.layer.bounds;
gradientLayer.colors = [NSArray arrayWithObjects: (id)[[UIColor whiteColor] colorWithAlphaComponent:0.5].CGColor,(id) colorTwo.CGColor,(id) colorThree.CGColor,(id) colorFour.CGColor, nil];
gradientLayer.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:1.0f], nil];
self.myButton.layer.cornerRadius = 5;
gradientLayer.cornerRadius = self.myButton.layer.cornerRadius;
[self.myButton.layer addSublayer:gradientLayer];
Now when my button is highlighted (touchedDown method called), I want to set new gradient to myButton. Hence I need to remove the old gradient effect when myButton is clicked and add new gradient.
How to remove the old gradient effect ?
I tried
for (CALayer *layer in [self.loginScreenView.btnPowerBroking.layer.sublayers copy]){
if ([[layer name] isEqualToString:#"gradientLayer"]) {
NSLog(#"Gradient layer found.");
}
}
But I can't get it's gradient layer.
Thanks for your time. (:
You haven't set the name property to your gradientLayer object just set it and it will work.
gradientLayer.name = #"gradientLayer";
[self.myButton.layer addSublayer:gradientLayer];
In for loop's if statement remove the layer using this [layer removeFromSuperlayer];
Note : You are adding layer in myButton object in searching inside the btnPowerBroking check properly for that also, you need to search in button where you have added Layer.
Try this method...
[self.myButton.layer replaceSublayer:oldgradientLayer with:newgradientLayer];

Adding subview to CollectionViewCell just once (cell reuseability issues)

I would like to add a simple gradient at the bottom of each cell. In cellForItemAtIndexPath: I have the code:
CAGradientLayer *bottomFade = [CAGradientLayer layer];
bottomFade.name = #"Gradient";
bottomFade.frame = CGRectMake(0, cell.background.frame.size.height*0.8, cell.background.frame.size.width, cell.background.frame.size.height*0.2);
bottomFade.endPoint = CGPointMake(0.5, 1.0);
bottomFade.startPoint = CGPointMake(0.5, 0.0);
bottomFade.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.0 alpha:0.0f] CGColor], (id)[[UIColor colorWithWhite:0.0 alpha:0.2f] CGColor], nil];
[cell.background.layer addSublayer:bottomFade];
The problem is that when the cell is being scrolled, the sublayer is added over and over again, which obviously is not a desired effect.
I know how to handle reuseability issues when it comes to the UITableView, but what should I do when it comes to working with the UICollectionView?
I tried to set a custom cell property isConfigured, but when I checked for it in cellForItemAtIndexPath: the result was that only two cells were generated, and then they were repeating (honestly, I have absolutely no idea why).
What would you suggest to handle such a problem? Perhaps it would be better to add some custom code in the cell's subclass?
Put your code that only requires once inside 'awakeFromNib' so it won't be called twice or thrice on its life cycle
which would appear like this:
- (void)awakeFromNib {
[super awakeFromNib];
CAGradientLayer *bottomFade = [CAGradientLayer layer];
bottomFade.name = #"Gradient";
bottomFade.frame = CGRectMake(0, self.background.frame.size.height*0.8, self.background.frame.size.width, self.background.frame.size.height*0.2);
bottomFade.endPoint = CGPointMake(0.5, 1.0);
bottomFade.startPoint = CGPointMake(0.5, 0.0);
bottomFade.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.0 alpha:0.0f] CGColor], (id)[[UIColor colorWithWhite:0.0 alpha:0.2f] CGColor], nil];
[self.background.layer addSublayer:bottomFade];
}
I've already solved the problem ;).
In the cell's subclass:
-(void)layoutSubviews {
if (!self.isConfigured) {
CAGradientLayer *bottomFade = [CAGradientLayer layer];
bottomFade.name = #"Gradient";
bottomFade.frame = CGRectMake(0, self.background.frame.size.height*0.8, self.background.frame.size.width, self.background.frame.size.height*0.2);
bottomFade.endPoint = CGPointMake(0.5, 1.0);
bottomFade.startPoint = CGPointMake(0.5, 0.0);
bottomFade.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.0 alpha:0.0f] CGColor], (id)[[UIColor colorWithWhite:0.0 alpha:0.2f] CGColor], nil];
[self.background.layer addSublayer:bottomFade];
self.isConfigured = YES;
}
}
That does the trick just fine! However, I'm still quite curious about whether there's an easy fix for the problem in cellForItemAtIndexPath: or not.
The cellForItemAtIndexPath: method will be called every time the UICollectionView instance create or reuse a UICollectionViewCell, that's where the problem is.
I don't recommend you use the property like isConfigured, the cell should keep a BOOL variable, and will check the property every time layoutSubviews been called, its a waste of memory and performance.
As nferocious76 said, awakeFromNib: method, which will be called only once on its life cycle, is the best solution for this case.
By the way, as I can't comment, you should call [super layoutSubviews] at the begin of layoutSubviews method.

Shadow effects on ImageView in iOS

I am trying to provide a shadow effect to my Imageview just like in this image.
but the problem which I am facing it is that the shadow is actually visible from the bottom of the Imageview.
Here is the code which I have done to add the shadow. The color and all is still not matching with this one.
CAGradientLayer *shadow = [CAGradientLayer layer];
shadow.frame = CGRectMake(-100, 70, perspectiveView.frame.size.width,
perspectiveView.frame.size.height - 20);
shadow.startPoint = CGPointMake(1.0, 0.5);
shadow.endPoint = CGPointMake(0, 0.5);
shadow.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.0
alpha:0.4f] CGColor], (id)[[UIColor clearColor] CGColor], nil];
shadow.opacity = 1.0f;
[perspectiveView.layer addSublayer:shadow];
Please provide inputs. Also if the approach is wrong, feel free to guide me to any other approach.
Thanks in advance.
Also can anyone suggest how to provide a 3D border just like in the image which provides a slight width to the image view?
Perhaps, adding a shadow to the layer seems to work. You may want to try something like this:
// perspectiveView.transform = CGAffineTransformMakeRotation(-50.0f);
perspectiveView.layer.shadowOffset = CGSizeMake(10, 10);
perspectiveView.layer.shadowRadius = 5.0;
perspectiveView.layer.shadowOpacity = 0.6;
perspectiveView.layer.masksToBounds = NO;
You will need to playaround with these values to match your requirements. Hope this helps.
Here is my output:
Try this,
- (void)setShadow {
[perspectiveView.layer setShadowOffset:CGSizeMake(-5.0, 5.0)];
[perspectiveView.layer setShadowRadius:5.0];
[perspectiveView.layer setShadowOpacity:1.0];
}
you can use CALayer class , the layer can manage your visual aspects like background color, border, shadow and with it you can also manage the geometry of it content like size , transform etc .
visual effect(shadowing)
self.yourView.layer.shadowOffset = CGSizeMake(0, 3);
self.yourView.layer.shadowRadius = 5.0;
self.yourView.layer.shadowColor = [UIColor blackColor].CGColor;
self.yourView.layer.shadowOpacity = 1;
and you also used it for like self.yourView.layer.frame(Geometry)
more info https://developer.apple.com/library/ios/documentation/graphicsimaging/reference/CALayer_class/index.html
Below code work i have checked properly.
but Shikhar varshney can u check setShadow method call and perspectiveView is not nil.
- (void)setShadow {
perspectiveView.layer.shadowColor = [UIColor colorWithWhite:0.0
alpha:0.4f] CGColor;
perspectiveView.layer.shadowOffset = CGSizeMake(0, 1);
perspectiveView.layer.shadowOpacity = 1;
perspectiveView.layer.shadowRadius = 1.0;
perspectiveView.clipsToBounds = NO;
}

UIButton with a gradient layer slow

I am customizing the UIButton with GradientLayer. I see a performance issue as view loading slowly and looks like a Jerk effect. Also when changing the orientation its same. I am using this code for an iPad application. With normal UIButton its smooth loading / rotating.
I am using the sample code found in google (GradientButton class) and is working fine. The container UIViewController which is pushed onto navigationcontroller stack to display the screen.
Here is the code:
- (void)awakeFromNib {
[self initLayers];
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self initLayers];
}
return self;
}
- (void)initLayers {
[self initBorder];
[self addShineLayer];
[self addHighlightLayer];
self.clipsToBounds = YES;
}
- (void)initBorder {
CALayer *layer = self.layer;
layer.cornerRadius = 8.0f;
layer.masksToBounds = YES;
layer.borderWidth = 1.0f;
layer.borderColor = [UIColor colorWithWhite:0.5f alpha:0.2f].CGColor;
}
- (void)addShineLayer {
shineLayer = [CAGradientLayer layer];
shineLayer.frame = self.layer.bounds;
shineLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithWhite:1.0f alpha:0.4f].CGColor,
(id)[UIColor colorWithWhite:1.0f alpha:0.2f].CGColor,
(id)[UIColor colorWithWhite:0.75f alpha:0.2f].CGColor,
(id)[UIColor colorWithWhite:0.4f alpha:0.2f].CGColor,
(id)[UIColor colorWithWhite:1.0f alpha:0.4f].CGColor,
nil];
shineLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:0.5f],
[NSNumber numberWithFloat:0.5f],
[NSNumber numberWithFloat:0.8f],
[NSNumber numberWithFloat:1.0f],
nil];
// shineLayer.shouldRasterize = YES;
// shineLayer.rasterizationScale = [UIScreen mainScreen].scale;
[self.layer addSublayer:shineLayer];
}
#pragma mark -
#pragma mark Highlight button while touched
- (void)addHighlightLayer {
highlightLayer = [CALayer layer];
highlightLayer.backgroundColor = [UIColor colorWithRed:0.25f green:0.25f blue:0.25f alpha:0.75].CGColor;
highlightLayer.frame = self.layer.bounds;
highlightLayer.hidden = YES;
[self.layer insertSublayer:highlightLayer below:shineLayer];
}
- (void)setHighlighted:(BOOL)highlight {
highlightLayer.hidden = !highlight;
[super setHighlighted:highlight];
}
Is the performance issue due to Gradient Layer ?? Please tell me how to rectify this issue.
Try commenting out the different property assignments in your code one at a time and see if you get any performance benefit. I worked on an app once that was getting about 12FPS in core animation when I used setCornerRadius on the layer compared to nearly full frame rate when I turned that off. The issue may be your gradient, however, you won't know for sure unless you just do some a/b comparisons turning off/on the various properties.
I'll tell you right now, though, that when I've used gradient layers on buttons in table view cells, I was able to speed up the table scrolling dramatically when I just used a background image for the button instead of a gradient layer. You can try to turn on shouldRasterize, however, make sure you do that at the top level of your layer tree and not on any sublayers (although the issues that I saw with setting that parameter on all layers may have been fixed in iOS6. I just haven't tested it).

Grandient background for a view on iOS

I'm pretty new to iOS developpement, and I'm trying to set my view background to a gradient.
I created a CAGradientLayer and try to set it. It goes throught building, but my app crashes as soon as it open, throwing a "EXC_BAD_ACCESS".
Here is my code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CAGradientLayer *bgLayer = [CAGradientLayer layer];
UIColor *grey = [UIColor colorWithRed:(255/255.0) green:(255/255.0) blue:(255/255.0) alpha:1.0];
UIColor *black = [UIColor colorWithRed:(180/255.0) green:(180/255.0) blue:(180/255.0) alpha:1.0];
NSNumber *top = [NSNumber numberWithFloat:0.0];
NSNumber *bot = [NSNumber numberWithFloat:1.0];
bgLayer.colors = [NSArray arrayWithObjects:grey, black, nil];
bgLayer.locations = [NSArray arrayWithObjects:top, bot, nil];
bgLayer.frame = self.view.bounds;
[self.view.layer addSublayer:bgLayer];
}
I think I understood that it comes from a bad memory management, but don't what I did wrong. Thanks for your answers in advance.
Note what the docs say about the colors:
An array of CGColorRef objects defining the color of each gradient stop.

Resources