如何让处理程序重复UIView animateWithDuration?

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

假设您已创建已取消的属性,则可以执行此类操作。 如注释中所述,完成块的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]; }]; } } ]; } 

动画的目的是重复动画图像的反弹。 当不用担心手动停止它时,你只需要设置三个属性(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。

实际上,递归调用的解决方案对我来说没有用。 动画开始表现得很奇怪:每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]; } }]; } 

你可以使用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"];