I am trying to delay the animation of layer's opacity and position by 3 seconds using setBeginTime. I have called the layer boxLayer. The animation is going well however during the first 3 seconds (the layer is not supposed to show yet) the layer is displayed at its final position and opacity. It should not. Group animation does not resolve the issue. Could anyone help? See code below:
// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// Maintain opacity to 1.0 JUST TO MAKE SURE IT DOES NOT GO BACK TO ORIGINAL OPACITY
[boxLayer setOpacity:endOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// Maintain the end position at 400.0 450.0 OTHERWISE IT IS GOING BACK TO ORIGINAL POSITION
[boxLayer setPosition:CGPointMake(endX, endY)];
This article explains well why you shouldn't use removedOnCompletion with fillMode https://www.objc.io/issues/12-animations/animations-explained/
In my case I'm animating the layer of a view that functions as a navigation but delaying a bounce animation that is inside that view ; I NEED BOTH OF THESE POSITIONS UPDATED ON THE LAYER since it can be dismissed and then shown again. Using removedOnCompletion will not update the layer's value once the animation completes
The way I do it is update the layer in a CATransaction completion block
The problem is that you're setting the
boxLayer
properties ofposition
and ofopacity
to their end values. You need to:Set the
boxLayer
properties to their starting values, not their ending values (this is why it's starting in the ending position/opacity ... usually if the animation starts immediately, this isn't an issue, but because you're deferring the start, using the ending positions is problematic);For your two animations, you have to change
removedOnCompletion
toNO
andfillMode
tokCAFillModeForwards
(this is the correct way to keep it from reverting back to the original position upon completion).Thus:
Personally, I think you're doing a lot of work for something that's done far more easily with block-based animation on the view (for the purposes of this demonstration, I'm assuming your
boxLayer
is aCALayer
for a control calledbox
). You don't need Quartz 2D, either, if you do it this way:For using
beginTime
you should make necessary configuration of your animation object and setfillMode
tokCAFillModeBackwards
likeThat's said in Apple documentation:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/AdvancedAnimationTricks/AdvancedAnimationTricks.html#//apple_ref/doc/uid/TP40004514-CH8-SW2
Also, from Rob's question:
It's a kind of controversial statement, because:
From https://www.objc.io/issues/12-animations/animations-explained/