web-dev-qa-db-fra.com

Existe-t-il un moyen de mettre en pause une CABasicAnimation?

J'ai une animation de base en rotation de l'iPhone. Existe-t-il un moyen de "suspendre" l'animation pour que la position de la vue soit conservée? J'imagine qu'une façon de procéder serait de faire en sorte que l'animation soit "complète" au lieu d'appeler "supprimer", comment pourrais-je procéder?

CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2];
rotationAnimation.duration = 100;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = HUGE_VALF;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
[myView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
45
mclaughlinj

La note technique récemment publiée par Apple QA1673 explique comment mettre en pause/reprendre l'animation de la couche.

La liste des animations en pause et reprise est la suivante:

-(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;
}

Edit: IOS 10 a introduit la nouvelle API - UIViewPropertyAnimator qui permet de gérer les animations de manière plus interactive, par exemple, il est facile de suspendre et de reprendre l'animation ou de la "rechercher" avec une valeur de progression particulière.

148
Vladimir

Réponse pour Swift 3: 

Crédits @Vladimir

Code:

 func pauseAnimation(){
  var pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
  layer.speed = 0.0
  layer.timeOffset = pausedTime
}

func resumeAnimation(){
  var pausedTime = layer.timeOffset
  layer.speed = 1.0
  layer.timeOffset = 0.0
  layer.beginTime = 0.0
  let timeSincePause = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
  layer.beginTime = timeSincePause
}
10

Définissez l'état actuel de la couche de votre vue pour qu'il corresponde à celui de la variable presentationLayer, puis supprimez l'animation:

CALayer *pLayer = [myView.layer presentationLayer];
myView.layer.transform = pLayer.transform;
[myView.layer removeAnimationForKey:@"rotationAnimation"];
6
gerry3

Vous pouvez utiliser un timer ou gérer la méthode de délégation d'animation:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag

Voici mon code:

// ...
[self startAnimation];
// ...

- (void)startAnimation {
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithFloat:0];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_2_PI];
rotationAnimation.duration = 1.0;
rotationAnimation.cumulative = YES;
// rotationAnimation.repeatCount = 0; // <- if repeatCount set to infinite, we'll not receive the animationDidStop notification when the animation is repeating
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.delegate = self; // <- hanlde the animationDidStop method
[myView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if (shouldContinueAnimation) // <- set a flag to start/stop the animation
    [self startAnimation];
}

J'espère que ça peut t'aider.

0
h7ing