取消 UIView 动画?
-
23-08-2019 - |
题
是否可以取消 UIView
动画正在进行时?还是我必须降到CA级别?
IE。我做了类似的事情(也许也设置了结束动画动作):
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties
// set view properties
[UIView commitAnimations];
但是在动画完成并且我收到动画结束事件之前,我想取消它(简短地说)。这可能吗?谷歌搜索发现有几个人问同样的问题但没有答案 - 并且一两个人猜测这是不可能完成的。
解决方案
我做的方式是创建一个新的动画到你的终点。设置一个持续时间很短,并确保您使用+setAnimationBeginsFromCurrentState:
方法从当前状态开始。当你将它设置为YES,当前动画被缩短。看起来是这样的:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.1];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties
// set view properties
[UIView commitAnimations];
其他提示
使用:
#import <QuartzCore/QuartzCore.h>
.......
[myView.layer removeAllAnimations];
最简单的方法来阻止所有上的特定视图的动画,立即,是这样的:
关联的项目QuartzCore.framework。在你的代码的启动:
#import <QuartzCore/QuartzCore.h>
现在,当你想停止在视图上死了所有的动画在其轨道,这样说:
[CATransaction begin];
[theView.layer removeAllAnimations];
[CATransaction commit];
在中间线将所有的工作本身,但有一个延迟,直到runloop完成(“重绘时刻”)。为了防止这种情况延迟,在一个明确的事务块包裹命令,如图所示。没有提供其他改变这个作品已经在当前runloop该层上执行的。
在的iOS 4和更大的,使用的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;
}
}];
}
要取消你只需要设置当前正被动画,所述动画的UIView外的属性的动画。这将停止动画无论是和UIView的将跳转到你刚才定义的设置。
对不起复活这个答案,但在iOS的10件事有点变了,现在取消是可能的,你甚至可以优雅地取消!
10的iOS后,你可以取消动画与 UIViewPropertyAnimator !
UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: {
view.backgroundColor = .blue
})
animator.stopAnimation(true)
如果您通过真它取消动画并在您取消它,它就停。完成方法将不会被调用。然而,如果传递假你是负责完成动画:
animator.finishAnimation(.start)
您可以完成你的动画,并留在当前状态(.current)或到初始状态(。开始)或结束状态(.END)
顺便说一句,你甚至可以暂停和稍后重新启动...
animator.pauseAnimation()
animator.startAnimation()
请注意:如果你不想要的突然取消,你可以扭转你的动画,甚至改变你的动画暂停后,
如果你正在通过改变,而不是一个视图属性没有其它方法的恒定动画的约束在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];
}
以上都没有为我解决这个问题,但这有帮助:这 UIView
动画立即设置属性,然后为其设置动画。当表示层与模型(设置属性)匹配时,它会停止动画。
我解决了我的问题,即“我想从你看起来像你出现的地方制作动画”(“你”指的是视图)。如果你想要那个,那么:
- 添加 QuartzCore。
CALayer * pLayer = theView.layer.presentationLayer;
将位置设置为表示层
我使用一些选项,包括 UIViewAnimationOptionOverrideInheritedDuration
但由于苹果的文档含糊不清,我不知道它在使用时是否真的会覆盖其他动画,或者只是重置计时器。
[UIView animateWithDuration:blah...
options: UIViewAnimationOptionBeginFromCurrentState ...
animations: ^ {
theView.center = CGPointMake( pLayer.position.x + YOUR_ANIMATION_OFFSET, pLayer.position.y + ANOTHER_ANIMATION_OFFSET);
//this only works for translating, but you get the idea if you wanna flip and scale it.
} completion: ^(BOOL complete) {}];
目前这应该是一个不错的解决方案。
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
我有同样的问题;这些API没有什么要取消一些特定的动画。在
+ (void)setAnimationsEnabled:(BOOL)enabled
禁用所有动画,因此对我不起作用。有两种解决方法:
1)使你的动画对象子视图。然后,当你想取消动画该视图,删除视图或隐藏。很简单,但你需要,如果你需要保持它在检视重新而不动画子视图。
2)重复动画只有一个,并根据需要进行委托选择器重新启动动画,像这样:
-(void) startAnimation {
NSLog(@"startAnim alpha:%f", self.alpha);
[self setAlpha:1.0];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(pulseAnimationDidStop:finished:context:)];
[self setAlpha:0.1];
[UIView commitAnimations];
}
- (void)pulseAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if(hasFocus) {
[self startAnimation];
} else {
self.alpha = 1.0;
}
}
-(void) setHasFocus:(BOOL)_hasFocus {
hasFocus = _hasFocus;
if(hasFocus) {
[self startAnimation];
}
}
使用2问题)是有总是延迟停止动画,因为它完成当前动画周期。
希望这有助于。
即使取消上述方式动画didStopSelector
仍然运行动画。所以,如果你有逻辑状态在您的应用程序通过动画驱动的,你将有问题。出于这个原因与以上I中描述的方式使用UIView
动画的上下文变量。如果您通过上下文参数去动画,程序的当前状态,当动画停止你的didStopSelector
功能可以决定是否应该做些什么或者基于当前的状态和情境传递的状态值刚刚返回。
的斯蒂芬达林顿氏溶液夫特版本
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.1)
// other animation properties
// set view properties
UIView.commitAnimations()
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
self.frame = pLayer.frame;
}];
要暂停的动画,而不还原状态,以原始或最终:
CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;
当我与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)
}
为我工作的回答没有一个方案。我解决了我的问题,这种方式(我不知道这是否是一个正确的方式?),因为我打电话时这也快(当一个动画还没有完成)有问题。我通过我想要的动画与的 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()
}
})
}
}