简体   繁体   English

CABasicAnimation代替UIView动画

[英]CABasicAnimation instead of UIView animation

I have the following animation block, to do some kind of a marquee label effect. 我有以下动画块,做一些字幕标签效果。
I have two labels and I scroll both, when the scroll animation is finished, I set new frames and scroll again. 我有两个标签,我滚动两个,当滚动动画完成后,我设置新帧并再次滚动。 the animation never stops. 动画永远不会停止。

- (void)scrollAwayWithInterval:(NSTimeInterval)interval delay:(NSTimeInterval)delay {
    [UIView animateWithDuration:interval
                          delay:delay
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         self.label.frame = _labelDestRect;
                         self.subLabel.frame = _subLabelDestRect;
                     }
                     completion:^(BOOL finished) {
                         if (finished) {
                             if (self.subLabel.frame.origin.x > 0) {
                                 [self prepareFramesForStep2];
                             } else {
                                 [self prepareFramesForStep1];
                             }

                             [self scrollAwayWithInterval:interval delay:delay];
                         }
                     }];
}

I need a way to pause/resume the animation, so I want to do the same animation with CABasicAnimation . 我需要一种暂停/恢复动画的方法,所以我想用CABasicAnimation做同样的动画。

So my question is, what is the equivalent way to do the following animation with CABasicAnimation ? 所以我的问题是,使用CABasicAnimation进行以下动画的等效方法是什么?

It is actually possible to pause UIView animations. 实际上可以暂停UIView动画。 It works because under the covers, iOS creates CAAnimations on the layer of the view(s) that you are animating. 它的工作原理是因为在幕后,iOS会在您正在制作动画的视图层上创建CAAnimations。 I have a sample project on github called KeyframeViewAnimations that demonstrates exactly this. 我在github上有一个名为KeyframeViewAnimations的示例项目,它正是如此。

If you are animating 2 different views at once, you might need to either manipulate the speed property on the layer of the superview that contains both views, or pause the animation on both view's layers separately. 如果要同时为2个不同的视图设置动画,则可能需要在包含两个视图的superview图层上操作speed属性,或者分别在两个视图的图层上暂停动画。 (I haven't tried pausing UIView animations on multiple views at the same time before, so I'm not totally sure if setting the speed property on the superview's layer will work or not.) (我之前没有尝试在多个视图上暂停UIView动画,所以我不完全确定在superview的图层上设置speed属性是否有效。)

Edit: I just tried it, and setting the speed on the superview's layer pauses both animations. 编辑:我刚尝试过,在superview的图层上设置速度会暂停两个动画。 The pause/resume code I put on a pause/resume button looks like this: 我在暂停/恢复按钮上设置的暂停/恢复代码如下所示:

- (IBAction)handlePauseButton:(UIButton *)sender
{
  animationIsPaused = !animationIsPaused;
  if (animationIsPaused)
  {
    [pauseButton setTitle: @"Resume" forState: UIControlStateNormal];
    CALayer *theLayer = animationContainerView.layer;

    //Freeze the animation.
    theLayer.speed = 0;

    //Calculate how far we into the animation based on current media time minus the media time when
    //The animation started.

    //Shift the layer's timing so it appears at the current time.
    theLayer.timeOffset = CACurrentMediaTime()-theLayer.beginTime;
    theLayer.beginTime = 0;
  }
  else
  {
    [pauseButton setTitle: @"Pause" forState: UIControlStateNormal];
    CALayer *theLayer = animationContainerView.layer;

    CFTimeInterval pausedTime = [theLayer timeOffset];

    //Now reset the time offset and beginTime to zero.
    theLayer.timeOffset = 0.0;
    theLayer.beginTime = 0.0;

    //Figure out how much time has elapsed since the animation was paused.
    CFTimeInterval timeSincePause = CACurrentMediaTime() - pausedTime;

    //Set the layer's beginTime to that time-since-pause
    theLayer.beginTime = timeSincePause;

    //Start the animation running again
    theLayer.speed = 1.0;
  }
}

You could still use this block. 你仍然可以使用这个块。

All you need to add is a BOOL variable that you can set to NO in a press of a button (or however you want) and the just set it as: 您需要添加的是BOOL变量,只需按一下按钮(或者您想要的话)就可以将其设置为NO,并将其设置为:

- (void)scrollAwayWithInterval:(NSTimeInterval)interval delay:(NSTimeInterval)delay {
    [UIView animateWithDuration:interval
                          delay:delay
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         self.label.frame = _labelDestRect;
                         self.subLabel.frame = _subLabelDestRect;
                     }
                     completion:^(BOOL finished) {
                         if (finished) {
                             if (shouldContinueAnimation) {
                                 if (self.subLabel.frame.origin.x > 0) {
                                     [self prepareFramesForStep2];
                                 } else {
                                     [self prepareFramesForStep1];
                                 }

                                 [self scrollAwayWithInterval:interval delay:delay];
                             }
                         }
                     }];
}

where shouldContinueAnimation is your BOOL. shouldContinueAnimation是你的BOOL。

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM