pzo
pzo

Reputation: 2157

Stopping core animation on layer when some condition is met

I'm trying to make 2 core animations that start at the same time and use the same curve but one of them need to be stopped if the condition is met. E.g. I have the following view on the left and want to transition to the right one.

enter image description here

The red views can be treated as overlays on top of yellow views even though in the beginning they are not intersecting. Imagine clicking 'item 3'. What I need to do is to animate movement of all rows to the top with distance -item3.frame.origin.y but once title3 reaches top of the screen it should stay there so the remaining item1 item2 will look like they are sliding behind title3

I tried to animate all elements using core animation with option: UIViewAnimationsOptionLayoutSubviews and then in layoutSubview stop the animation with the following code:

-(void)layoutSubviews {
    CALayer* presentationLayer = (CALayer*)[self.title3.layer presentationLayer];
    if (presentationLayer.frame.origin.y <= 0) {
        [self.title3.layer removeAllAnimations];
    }
}

but without any success. Is there any way to make it work using core animation and without mocking with CADisplayLink. I can't use two seperate animations because the duration for title3 animations is hard to calculate which creates a gap between title3 and title2 if the animation curve is not linear.

Upvotes: 0

Views: 234

Answers (1)

Neil Galiaskarov
Neil Galiaskarov

Reputation: 5073

You can implement pause/start layer animation feature according Apple's technical note QA1673 by following code:

-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}

Upvotes: 0

Related Questions