Transition animation does not take place for every text change - ios

I have added transition animation to UILabel for text change.
But it takes place only once when I add it to layer.
- (IBAction)changeText:(id)sender {
if (!self.transitionAnimation) {
CATransition *animation = [CATransition animation];
animation.duration = 0.5;
animation.type = kCATransitionFade;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.removedOnCompletion = NO;
[self.label.layer addAnimation:animation forKey:nil];
self.transitionAnimation = animation;
}
self.label.text = [NSString stringWithFormat:#"Text %d",arc4random()];
}

Why do you need to have a strong reference to the animation? That reference doesn't get nil'ed out, and hence your control doesn't enter the if block more than once.
Either nil out the transitionAnimation property on didStop, or don't store a reference at all.
Edit: Also, I don't think you need to have removedOnCompletion as NO.

Related

I set the toValue of rotation to 2*PI, but why after the animation these views are not horizontal?

Codes are as follows:
CABasicAnimation *rotateWhenBoom = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotateWhenBoom.fromValue = #0;
rotateWhenBoom.toValue = #(M_PI*2.0);
rotateWhenBoom.duration = 0.3f;
rotateWhenBoom.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CAAnimationGroup *boom = [CAAnimationGroup animation];
boom.animations = #[[self moveOutWithBtn:btn], rotateWhenBoom];
boom.fillMode = kCAFillModeForwards;
boom.removedOnCompletion = NO;
And the effect:
effect
Before the animation the views are all horizontal. I add a rotation animation to these views, and the toValue of rotation is 2*PI. Why after the animation they are not horizontal?
Thanks in advance!!
Your last two lines of code:
boom.fillMode = kCAFillModeForwards;
boom.removedOnCompletion = NO;
mean that the layer stays at the final state of animation and that the animation is not automatically removed from the layer when it completes. You probably want to remove the last line boom.removeOnCompletion = NO
A good guide for CALayer and CAAnimation that explains this: https://www.objc.io/issues/12-animations/animations-explained/

Identifying CAAnimation in animationDidStop callback failing

How to identify CAAnimation after completion? I tried KVO by setting a string value as animationID and checking it in animationDidStop method. But KVO returns an integer sometimes instead of a string animationID and the app is crashing.
Here is my code:
-(void)moveLayer:(CALayer*)layer to:(CGPoint)point duration:(NSTimeInterval)duration animationID:(NSString*)animationid
{
// Prepare the animation from the current position to the new position
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.fromValue = [layer valueForKey:#"position"];
[animation setDuration:duration];
animation.toValue = [NSValue valueWithCGPoint:point];
animation.delegate=self;
[animation setValue:animationid forKey:#"animationID"];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
// Update the layer's position so that the layer doesn't snap back when the animation completes.
layer.position = point;
// Add the animation, overriding the implicit animation.
[layer addAnimation:animation forKey:#"position"];
}
and callback is:
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
if (flag) {
id animationIDString=[animation valueForKey:#"animationID"];
// this is coming as an int value sometimes and the code below this fails ..
if([animationIDString isEqual:#"animation1"]) {
//animation is animation1
_movieBalloonImageView.hidden=NO;
_storiesBalloonImageView.hidden=NO;
_rhymesBalloonImageView.hidden=NO;
[self.navigationController popViewControllerAnimated:NO];
}
}
}
What can be the possible reason? Is it because the animation gets destroyed before this delegate gets called?
I am setting removedOnCompletion to NO and fillmode to kCAFillModeForwards.But the code is not working as expected.
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
Or is there any alternative method to do this? I am calling the moveLayer method in several places in the viewController.

What's the meaning of progress keypath in CABasicAnimation?

A code snippet from https://github.com/danielamitay/DACircularProgress/blob/master/DACircularProgress/DACircularProgressView.m
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"progress"];
animation.duration = duration;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fillMode = kCAFillModeForwards;
animation.fromValue = [NSNumber numberWithFloat:self.progress];
animation.toValue = [NSNumber numberWithFloat:pinnedProgress];
animation.beginTime = CACurrentMediaTime() + initialDelay;
animation.delegate = self;
[self.circularProgressLayer addAnimation:animation forKey:#"progress"];
But I could not find progress in the offical document. Does the keypath need to be animatable property? What does the progress mean?
From this answer (which is coincidentally animating progress too):
Firstly we need to create a new subclass of CALayer that has an animatable property called 'progress'.
Your snippet does indeed have a property called 'progress'
#property(nonatomic) CGFloat progress;
It appears the animation is animating that property
It is because the progress is an animatable property for this specific uiview. We could custom animatable property refer: Create a custom animatable property

Implicit animation on CALayer "contents" property

According to the core animation documentation, setting the layer contents should trigger an implicit 0.25 animation that will transition between the new and old images.
I also see many places where people are asking how to remove this implicit animation but for some reason when I try this on my project, I get an instant swap of images.
Reading some more into the documention I saw this code snipped:
- (id<CAAction>)actionForLayer:(CALayer *)theLayer
forKey:(NSString *)theKey {
CATransition *theAnimation=nil;
if ([theKey isEqualToString:#"contents"]) {
theAnimation = [[CATransition alloc] init];
theAnimation.duration = 1.0;
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
theAnimation.type = kCATransitionPush;
theAnimation.subtype = kCATransitionFromRight;
}
return theAnimation;
}
Which implies that "contents" is not implicitly animated.
I would be very interested to understand this better.
OK, I'm copying some code from an app of mine. First I usually get CATransition not with alloc..init.. but using +animation. Second I'm not seeing that you are adding the transition to a layer. Third I'm not sure that CATransition are implicitly animated, CALayer properties yes.
CATransition *transition = [CATransition animation];
transition.duration = 1;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = slideCATransitionCompareTable[ arc4random() % 4]; //to get a random subtype
[self.slideShowReceiptImageView.layer addAnimation:transition forKey:nil];

Glitch when sliding in UIView with kCATransitionMoveIn

I have a UINavigationController whose UIView slides in from the bottom of the screen when the user presses a button.
Immediately after I set the view's "hidden" property to NO, though, the UINavigationController's view sometimes appears fully in place for one frame, as if the animation was finished already.
This is the code that shows/hides the view:
- (void)showGUI: (bool)show
{
CATransition *transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
if (!show)
{
transition.type = kCATransitionReveal;
transition.subtype = kCATransitionFromBottom;
}
else
{
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromTop;
}
[navController.view.superview.layer addAnimation:transition forKey:nil];
navController.view.hidden = !show;
}
CATransition animations are applied when layers are added/removed from the layer you add the animation to. If toggling the hidden property doesn't work, then try removing the view instead.

Resources