是否有可能取消一个UIView动画,而它正在进行中?或者我必须降到CA级别?
例如,我做过这样的事情(可能设置了一个结束动画动作):
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties
// set view properties
[UIView commitAnimations];
但是在动画完成之前,我得到动画结束事件,我想取消它(缩短它)。这可能吗?在谷歌上搜索一下,会发现一些人问了同样的问题,但没有答案——还有一两个人猜测这是不可能的。
如果你通过改变常量而不是视图属性来动画约束,其他方法在iOS 8上都不起作用。
示例动画:
self.constraint.constant = 0;
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^{
self.constraint.constant = 1.0f;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
}];
解决方案:
您需要从任何受约束更改影响的视图的层及其子层中删除动画。
[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
[l removeAllAnimations];
}
很抱歉要恢复这个答案,但在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()
注意:如果你不想突然取消,你可以反转你的动画,甚至在你暂停它后改变你的动画!
当我使用UIStackView动画时,除了removeAllAnimations()之外,我需要将一些值设置为初始值,因为removeAllAnimations()可以将它们设置为不可预知的状态。我有stackView与view1和view2在里面,一个视图应该是可见的和一个隐藏:
public func configureStackView(hideView1: Bool, hideView2: Bool) {
let oldHideView1 = view1.isHidden
let oldHideView2 = view2.isHidden
view1.layer.removeAllAnimations()
view2.layer.removeAllAnimations()
view.layer.removeAllAnimations()
stackView.layer.removeAllAnimations()
// after stopping animation the values are unpredictable, so set values to old
view1.isHidden = oldHideView1 // <- Solution is here
view2.isHidden = oldHideView2 // <- Solution is here
UIView.animate(withDuration: 0.3,
delay: 0.0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
view1.isHidden = hideView1
view2.isHidden = hideView2
stackView.layoutIfNeeded()
},
completion: nil)
}