如何制止和扭转一个UIView动画? [英] How to stop and reverse a UIView animation?

查看:125
本文介绍了如何制止和扭转一个UIView动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有动画一个UIView以便它当用户触摸一个切换按钮收缩并且当用户再次触摸该按钮其膨胀回其原始尺寸。到目前为止,一切都运行得很好。问题是,在动画需要一些时间 - 例如3秒。那段时间我还是希望用户能够与之交互的界面。因此,当用户再次触摸按钮,而动画仍在进行动画应该就停在那里它和逆转。

I have animated a UIView so that it shrinks when the user touches a toggle button and it expands back to its original size when the user touches the button again. So far everything works just fine. The problem is that the animation takes some time - e.g. 3 seconds. During that time I still want the user to be able to interact with the interface. So when the user touches the button again while the animation is still in progress the animation is supposed to stop right where it is and reverse.

在苹果Q&放大器;正如我已经找到一种方法,立即暂停所有动画:

In the Apple Q&As I have found a way to pause all animations immediately:

<一个href=\"https://developer.apple.com/library/ios/#qa/qa2009/qa1673.html\">https://developer.apple.com/library/ios/#qa/qa2009/qa1673.html

但我不明白的方式扭转从这里动画(并省略初始动画的其余部分)。我如何做到这一点?

But I do not see a way to reverse the animation from here (and omit the rest of the initial animation). How do I accomplish this?

- (IBAction)toggleMeter:(id)sender {
    if (self.myView.hidden) {        
        self.myView.hidden = NO;
        [UIView animateWithDuration:3 animations:^{
            self.myView.transform = expandMatrix;
        } completion:nil];
    } else {
        [UIView animateWithDuration:3 animations:^{
            self.myView.transform = shrinkMatrix;
        } completion:^(BOOL finished) {
            self.myView.hidden = YES;
        }];
    }
}


推荐答案

在除以下(其中我们抓住从presentation层的当前状态,停止动画,从保存的$重置当前状态p $ psentation层,并开始新的动画),有一个更容易的解决方案。

In addition to the below (in which we grab the current state from the presentation layer, stop the animation, reset the current state from the saved presentation layer, and initiate the new animation), there is a much easier solution.

如果做基于块的动画,如果你想之前的8.0停止动画并启动在IOS版本一个新的动画,你可以简单地使用 UIViewAnimationOptionBeginFromCurrentState 选项。 (有效iOS中8,默认行为是不仅从当前的状态开始,但在这既反映了当前位置的方式,以及当前速度的话,使得它在很大程度上不必担心这个问题在所有见2014年WWDC视频大厦中断和响应交互了解更多信息。)

If doing block-based animations, if you want to stop an animation and launch a new animation in iOS versions prior to 8.0, you can simply use the UIViewAnimationOptionBeginFromCurrentState option. (Effective in iOS 8, the default behavior is to not only start from the current state, but to do so in a manner that reflects both the current location as well as the current velocity, rendering it largely unnecessary to worry about this issue at all. See WWDC 2014 video Building Interruptible and Responsive Interactions for more information.)

[UIView animateWithDuration:3.0
                      delay:0.0
                    options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
                 animations:^{
                     // specify the new `frame`, `transform`, etc. here
                 }
                 completion:NULL];


您可以通过停止当前的动画,并开始从那里当前的离开了新的动画实现这一目标。为此,您可以用<一个href=\"https://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/Introduction/Introduction.html\">Quartz 2D :


  1. <一个href=\"http://developer.apple.com/library/mac/#recipes/x$c$c_help-project_editor/Articles/AddingaLibrarytoaTarget.html\">Add QuartzCore.framework到项目如果您还没有。 (在X code当代版本中,它通常没有必要去明确地做到这一点,因为它会自动链接到该项目。)

  1. Add QuartzCore.framework to your project if you haven't already. (In contemporary versions of Xcode, it is often unnecessary to explicitly do this as it is automatically linked to the project.)

导入必要的头,如果你还没有准备好(同样,没有必要在X $ C $的C当代版本):

Import the necessary header if you haven't already (again, not needed in contemporary versions of Xcode):

#import <QuartzCore/QuartzCore.h>


  • 让你的code停止现有动画:

  • Have your code stop the existing animation:

    [self.subview.layer removeAllAnimations];
    


  • 获取当前presentation层的引用(即视图的状态,因为它是precisely在这一刻):

  • Get a reference to the current presentation layer (i.e. the state of the view as it is precisely at this moment):

    CALayer *currentLayer = self.subview.layer.presentationLayer;
    


  • 重置变换根据当前值(或或其他)的 presentationLayer

  • Reset the transform (or frame or whatever) according to the current value in the presentationLayer:

    self.subview.layer.transform = currentLayer.transform;
    


  • 现在从动画变换(或或其他)为新的值:

  • Now animate from that transform (or frame or whatever) to the new value:

    [UIView animateWithDuration:1.0
                          delay:0.0
                        options:UIViewAnimationOptionAllowUserInteraction
                     animations:^{
                         self.subview.layer.transform = newTransform;
                     }
                     completion:NULL];
    


  • 把所有在一起,下面是切换从2.0倍变换我的规模,以确定和背部例行:

    Putting that all together, here is a routine that toggles my transform scale from 2.0x to identify and back:

    - (IBAction)didTouchUpInsideAnimateButton:(id)sender
    {
        CALayer *currentLayer = self.subview.layer.presentationLayer;
    
        [self.subview.layer removeAllAnimations];
    
        self.subview.layer.transform = currentLayer.transform;
    
        CATransform3D newTransform;
    
        self.large = !self.large;
    
        if (self.large)
            newTransform = CATransform3DMakeScale(2.0, 2.0, 1.0);
        else
            newTransform = CATransform3DIdentity;
    
        [UIView animateWithDuration:1.0
                              delay:0.0
                            options:UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             self.subview.layer.transform = newTransform;
                         }
                         completion:NULL];
    }
    

    或者,如果你想切换尺寸从100×100到200×200,后:

    Or if you wanted to toggle frame sizes from 100x100 to 200x200 and back:

    - (IBAction)didTouchUpInsideAnimateButton:(id)sender
    {
        CALayer *currentLayer = self.subview.layer.presentationLayer;
    
        [self.subview.layer removeAllAnimations];
    
        CGRect newFrame = currentLayer.frame;
    
        self.subview.frame = currentLayer.frame;
    
        self.large = !self.large;
    
        if (self.large)
            newFrame.size = CGSizeMake(200.0, 200.0);
        else
            newFrame.size = CGSizeMake(100.0, 100.0);
    
        [UIView animateWithDuration:1.0
                              delay:0.0
                            options:UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             self.subview.frame = newFrame;
                         }
                         completion:NULL];
    }
    


    顺便说一句,但通常并不重要了非常快的动画,缓慢动画像你这样,你可能要设置的反转动画的持续时间是一样的,你已经多远你的进步当前的动画(例如,如果你是0.5秒变为3.0秒的动画,当你倒车,你可能不希望采取3.0秒扭转你迄今所做的动画小部分,而只是0.5秒)。因此,这可能是这样的:


    By the way, while it generally doesn't really matter for really quick animations, for slow animations like yours, you might want to set the duration of the reversing animation to be the same as how far you've progressed in your current animation (e.g., if you're 0.5 seconds into a 3.0 second animation, when you reverse, you probably don't want to take 3.0 seconds to reverse that small portion of the animation that you have done so far, but rather just 0.5 seconds). Thus, that might look like:

    - (IBAction)didTouchUpInsideAnimateButton:(id)sender
    {
        CFTimeInterval duration = kAnimationDuration;             // default the duration to some constant
        CFTimeInterval currentMediaTime = CACurrentMediaTime();   // get the current media time
        static CFTimeInterval lastAnimationStart = 0.0;           // media time of last animation (zero the first time)
    
        // if we previously animated, then calculate how far along in the previous animation we were
        // and we'll use that for the duration of the reversing animation; if larger than
        // kAnimationDuration that means the prior animation was done, so we'll just use
        // kAnimationDuration for the length of this animation
    
        if (lastAnimationStart)
            duration = MIN(kAnimationDuration, (currentMediaTime - lastAnimationStart));
    
        // save our media time for future reference (i.e. future invocations of this routine)
    
        lastAnimationStart = currentMediaTime;
    
        // if you want the animations to stay relative the same speed if reversing an ongoing
        // reversal, you can backdate the lastAnimationStart to what the lastAnimationStart
        // would have been if it was a full animation; if you don't do this, if you repeatedly
        // reverse a reversal that is still in progress, they'll incrementally speed up.
    
        if (duration < kAnimationDuration)
            lastAnimationStart -= (kAnimationDuration - duration);
    
        // grab the state of the layer as it is right now
    
        CALayer *currentLayer = self.subview.layer.presentationLayer;
    
        // cancel any animations in progress
    
        [self.subview.layer removeAllAnimations];
    
        // set the transform to be as it is now, possibly in the middle of an animation
    
        self.subview.layer.transform = currentLayer.transform;
    
        // toggle our flag as to whether we're looking at large view or not
    
        self.large = !self.large;
    
        // set the transform based upon the state of the `large` boolean
    
        CATransform3D newTransform;
    
        if (self.large)
            newTransform = CATransform3DMakeScale(2.0, 2.0, 1.0);
        else
            newTransform = CATransform3DIdentity;
    
        // now animate to our new setting
    
        [UIView animateWithDuration:duration
                              delay:0.0
                            options:UIViewAnimationOptionAllowUserInteraction
                         animations:^{
                             self.subview.layer.transform = newTransform;
                         }
                         completion:NULL];
    }
    

    这篇关于如何制止和扭转一个UIView动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆