是否有可能取消一个UIView动画,而它正在进行中?或者我必须降到CA级别?
例如,我做过这样的事情(可能设置了一个结束动画动作):
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties
// set view properties
[UIView commitAnimations];
但是在动画完成之前,我得到动画结束事件,我想取消它(缩短它)。这可能吗?在谷歌上搜索一下,会发现一些人问了同样的问题,但没有答案——还有一两个人猜测这是不可能的。
很抱歉要恢复这个答案,但在iOS 10中事情有点改变,现在取消是可能的,你甚至可以优雅地取消!
ios10之后,你可以用UIViewPropertyAnimator取消动画!
UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: {
view.backgroundColor = .blue
})
animator.stopAnimation(true)
如果你传递true,它会取消动画,并在你取消的地方停止。补全方法将不会被调用。然而,如果你传递了false,你将负责完成动画:
animator.finishAnimation(.start)
你可以完成动画并保持当前状态(.current)或回到初始状态(.start)或结束状态(.end)
顺便说一下,你甚至可以暂停并稍后重新启动……
animator.pauseAnimation()
animator.startAnimation()
注意:如果你不想突然取消,你可以反转你的动画,甚至在你暂停它后改变你的动画!
没有一个解决方案对我有效。我用这种方式解决了我的问题(我不知道这是否是正确的方式?),因为我在调用这个太快的时候有问题(当以前的动画还没有完成的时候)。我通过customAnim块传递我想要的动画。
extension UIView
{
func niceCustomTranstion(
duration: CGFloat = 0.3,
options: UIView.AnimationOptions = .transitionCrossDissolve,
customAnim: @escaping () -> Void
)
{
UIView.transition(
with: self,
duration: TimeInterval(duration),
options: options,
animations: {
customAnim()
},
completion: { (finished) in
if !finished
{
// NOTE: This fixes possible flickering ON FAST TAPPINGS
// NOTE: This fixes possible flickering ON FAST TAPPINGS
// NOTE: This fixes possible flickering ON FAST TAPPINGS
self.layer.removeAllAnimations()
customAnim()
}
})
}
}
在ios4及更高版本上,在第二个动画上使用UIViewAnimationOptionBeginFromCurrentState选项来缩短第一个动画。
例如,假设您有一个带有活动指示器的视图。您希望在一些潜在耗时的活动开始时淡出活动指示器,并在活动结束时淡出活动指示器。在下面的代码中,带有活动指示器的视图称为activityView。
- (void)showActivityIndicator {
activityView.alpha = 0.0;
activityView.hidden = NO;
[UIView animateWithDuration:0.5
animations:^(void) {
activityView.alpha = 1.0;
}];
- (void)hideActivityIndicator {
[UIView animateWithDuration:0.5
delay:0 options:UIViewAnimationOptionBeginFromCurrentState
animations:^(void) {
activityView.alpha = 0.0;
}
completion:^(BOOL completed) {
if (completed) {
activityView.hidden = YES;
}
}];
}