【问题标题】:How to have a handler to repeat UIView animateWithDuration?如何让处理程序重复 UIView animateWithDuration?
【发布时间】:2011-07-20 18:52:41
【问题描述】:

我正在使用 UIView 类方法 animateWithDuration 来重复我的视图动画。我怎样才能拥有一个可用于稍后停止此动画的处理程序?例如,重复的动画在一种方法中开始,我需要稍后从另一种方法中停止。

【问题讨论】:

  • 为什么不只是一个BOOL 告诉动画是否应该运行?

标签: iphone ios animation uiview repeat


【解决方案1】:

假设您创建了一个 canceled 属性,您可以执行类似的操作。如 cmets 中所述,完成块的 startAnimation 调用需要包装在异步调用中以避免堆栈溢出。请务必将“id”替换为您实际拥有的任何类类型。

- (void)startAnimation {
    [UIView animateWithDuration:1.0
                          delay:0.0
                        options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
                     animations:^(void) {
                         //animate
                     }
                     completion:^(BOOL finished) {
                         if(!self.canceled) {
                             __weak id weakSelf = self;
                             [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                 [weakSelf startAnimation];
                             }];
                         }
                     }
     ];
}

【讨论】:

  • 这最终不会填满堆栈吗?
  • 这会导致UI对象无限堆叠,因为当你调用方法时,进程会重新启动,它不是异步的。
【解决方案2】:

动画的目的是重复动画图像的反弹。当不用担心手动停止它时,你只需要设置三个属性(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat)和动画块代码来移动图像-self.image.center = CGPointMake(self.image.center.x, self.image.center.y+25);这里是动画的完整代码:

[UIView animateWithDuration:0.5 delay:0 options:( UIViewAnimationOptionCurveEaseIn | 
 UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | 
 UIViewAnimationOptionAllowUserInteraction) animations:^{self.image.center = 
 CGPointMake(self.image.center.x, self.image.center.y+25);} completion:nil];

就是这样。但是,如果您需要手动控制,则需要一些额外的代码。首先,根据 jaminguy 的说法,您需要有一个 BOOL 属性来指示循环/停止(self.playAnimationForImage)动画并使用将从其他地方调用的动画代码清除单独的方法。方法如下:

-(void)animateImageBounce{
 [UIView animateWithDuration:0.5 delay:0 options:( 
  UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAutoreverse |  
  UIViewAnimationOptionAllowUserInteraction) animations:^{self.image.center = 
  CGPointMake(self.image.center.x, self.image.center.y+25);} completion:^(BOOL finished){if 
  (finished && self.playAnimationForImage){
    self.image.center = CGPointMake(self.image.center.x, self.image.center.y-25); 
    [self animateImageBounce];
  }}]; 

这里是从某个方法调用动画的开始

-(void)someMethod{
...
self.playAnimationForFingers = YES;
[self animateImageBounce];

}

我要注意的是,在手动控制中,您需要在执行下一次递归调用之前将图像的 center.y 重置回来。

【讨论】:

  • 感谢无价提示:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
【解决方案3】:

实际上,递归调用的解决方案对我来说并不奏效。动画开始表现得很奇怪:每 2 到 3 个动画重复循环我就会出现动画中断。在项目的第一个弹跳部分(向下移动项目)之后,第二部分(向上移动)几乎立即执行。我认为这与递归调用有关。

因此,我拒绝使用它。解决方案是使用自动反转和重复选项启动动画,并在完整块中检查标志 (self.playAnimationForFingers) 是否指示停止动画。

-(void)animateFingersForLevelCompleteScreen{
  //fix: reset the place of bouncing fingers (starting place). 
  //Otherwise the fingers will slowly move to the bottom at every level. 
  //This resetting is not working when placed inside UIView 
  //animate complete event block

  self.image.center = CGPointMake(10 + self.image.frame.size.width/2, 
                                  95 + self.image.frame.size.height/2); 

  [UIView animateWithDuration:0.5 delay:0 
    options:(UIViewAnimationOptionCurveEaseIn | 
             UIViewAnimationOptionAutoreverse | 
             UIViewAnimationOptionRepeat |
             UIViewAnimationOptionAllowUserInteraction) 
    animations:^{
      self.image.center = CGPointMake(self.image.center.x, 
                                      self.image.center.y+25);
    } 
    completion:^(BOOL finished){
      /*finished not approapriate: finished will not be TRUE if animation 
      was interrupted. It is very likely to happen because animation repeats && */
      if (!self.playAnimationForFingers){
         [UIView setAnimationRepeatAutoreverses:NO]; 
      }
  }];
}

【讨论】:

    【解决方案4】:

    你可以使用 CABasicAnimation 代替。

        CABasicAnimation *appDeleteShakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    appDeleteShakeAnimation.autoreverses = YES;
    appDeleteShakeAnimation.repeatDuration = HUGE_VALF;
    appDeleteShakeAnimation.duration = 0.2;
    appDeleteShakeAnimation.fromValue = [NSNumber numberWithFloat:-degreeToRadian(5)];
    appDeleteShakeAnimation.toValue=[NSNumber numberWithFloat:degreeToRadian(5)];
    [self.layer addAnimation:appDeleteShakeAnimation forKey:@"appDeleteShakeAnimation"];
    

    然后当你想停止它时,你可以打电话

    [self.layer removeAnimationForKey:@"appDeleteShakeAnimation"];
    

    【讨论】:

      猜你喜欢
      • 2013-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多