Expect: CALayer disappear normally
Actual: CALayer flash (blink) before disappear
full source code:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.multipleTouchEnabled = YES;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch* touch in touches) {
CGPoint p = [touch locationInView:self.view];
//NSLog(@"touch=%@ p=%@", touch, NSStringFromCGPoint(p));
CALayer *layer = [CALayer layer];
layer.position = p;
layer.bounds = CGRectMake(0, 0, 70, 70);
layer.cornerRadius = 30;
layer.masksToBounds = NO;
layer.backgroundColor = [UIColor colorWithRed:102.0/255.0 green:156.0/255.0 blue:255.0/255.0 alpha:0.8].CGColor;
layer.shouldRasterize = YES;
CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeOutAnimation.fromValue = [NSNumber numberWithFloat:1.0];
fadeOutAnimation.toValue = [NSNumber numberWithFloat:0.0];
fadeOutAnimation.duration = 0.5;
fadeOutAnimation.delegate = self;
fadeOutAnimation.removedOnCompletion = NO;
[fadeOutAnimation setValue:layer forKey:@"parentLayer"];
[layer addAnimation:fadeOutAnimation forKey:@"opacity"];
[self.view.layer addSublayer:layer];
}
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
if(flag) {
CALayer *layer = [theAnimation valueForKey:@"parentLayer"];
if(layer) {
layer.opaque = NO;
layer.opacity = 0.0;
//layer.hidden = YES;
//NSLog(@"The layer object was: %@ (%@)", layer, [layer name]);
[layer removeFromSuperlayer];
[layer removeAllAnimations];
}
}
}
@end
tl;dr: Set the fillMode
on the animation to kCAFillModeForwards
or change the values to their final value prior to adding the animation to the layer.
A basic animation is only a visual animation during the time of the animation, no actual values are changed. When you set the animation to not be removed upon completion it means that the layer will still reference the animation object as one of its animations. It has however already ran its animation.
The default behavior of how animations look (their fill mode) is kCAFillModeRemoved
which means that just after the duration of the animation the layer will look as if the animation never happened. By changing the fill mode to either kCAFillModeForwards
or kCAFillModeBoth
you can make the layer look as if the layer remained in the end state of the animation.
You can do the same thing in the beginning of the animation with kCAFillModeBackwards
but it mostly applies when you have set a begin time for the animation.
So to make the animation look as it did in the final state of the animation you can either set the fill mode to ...Forwards
and not remove the animation or change the actual values of the layer to the values you expect them to be just before you add the animation to the view. This will change the values and then animate from the old value to the new.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With