取消UIView动画?

2020/10/31 23:02 · ios ·  · 0评论

是否可以UIView在进行动画时取消动画?还是我必须降至CA级别?

即我做了这样的事情(也许也设置了结束动画动作):

[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];

中间行本身可以工作,但是要等到运行循环结束(“重绘时刻”)后再进行延迟。为避免这种延迟,请如图所示将命令包装在显式事务块中。前提是当前运行循环中未对该层进行任何其他更改,则此项工作有效。

在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中,情况有所更改,现在可以取消,甚至可以优雅地取消!

在iOS 10之后,您可以使用UIViewPropertyAnimator取消动画

UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: {
    view.backgroundColor = .blue
})
animator.stopAnimation(true)

如果通过,则取消动画,并在取消动画的位置停止。完成方法将不会被调用。但是,如果传递false,则您有责任完成动画:

animator.finishAnimation(.start)

您可以完成动画并停留在当前状态(.current)或进入初始状态(.start)或结束状态(.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];
}

如果您只想平稳地暂停/停止动画

self.yourView.layer.speed = 0;

资料来源:如何暂停图层树的动画

上面的方法都没有为我解决它,但这有帮助:UIView动画立即设置属性,然后对其进行动画处理。当表示层与模型(set属性)匹配时,它将停止动画。

我解决了我的问题,即“我想从看起来像的位置开始制作动画”(“您”表示视图)。如果您想要那,那么:

  1. 添加QuartzCore。
  2. CALayer * pLayer = theView.layer.presentationLayer;

将位置设置为表示层

我使用一些选项,包括 UIViewAnimationOptionOverrideInheritedDuration

但是由于Apple的文档含糊不清,我不知道它在使用时是否真的会覆盖其他动画,或者只是重置计时器。

[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];

史蒂芬·达林顿解决方案的Swift版本

UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.1)
// other animation properties

// set view properties
UIView.commitAnimations()

我也有同样的问题; 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仍会运行。因此,如果您的应用程序中有由动画驱动的逻辑状态,那么您将遇到问题。基于上述原因,我使用UIView动画的上下文变量如果通过上下文参数将程序的当前状态传递给动画,则动画停止时,您的didStopSelector函数可以根据当前状态和作为上下文传递的状态值来决定是应该执行某些操作还是应返回。

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()可以将它们设置为不可预测的状态。我有stackViewview1view2里面,一个视图应该是可见的,一个隐藏的:

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()
                }
        })

    }

}
本文地址:http://ios.askforanswer.com/quxiaouiviewdonghua.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!