在苹果问答中我已经找到一种方法来暂停所有的动画:
https://developer.apple.com/library/ios/#qa/qa2009/qa1673.html
但我没有看到从这里扭转动画的方法(省略了其余的初始动画).我该如何做到这一点?
- (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; }]; } }
解决方法
如果要执行基于块的动画,如果要在8.0之前的iOS版本中停止动画并启动新的动画,可以使用UIViewAnimationOptionBeginFromCurrentState选项. (在iOS 8中有效,默认行为不仅是从当前状态开始,而是以反映当前位置以及当前速度的方式执行此操作,从而使其无需担心此问题请参阅WWDC 2014 video Building Interruptible and Responsive Interactions了解更多信息.)
[UIView animateWithDuration:3.0 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction animations:^{ // specify the new `frame`,`transform`,etc. here } completion:NULL];
您可以通过停止当前动画并从当前的动画开始新的动画来实现此目的.您可以使用Quartz 2D:
> Add QuartzCore.framework to your project如果你还没有(在Xcode的当代版本中,通常不需要明确地这样做,因为它自动链接到项目.)
>如果您还没有(再次,Xcode的当代版本不需要),则导入必要的标题:
#import <QuartzCore/QuartzCore.h>
>让你的代码停止现有的动画:
[self.subview.layer removeAllAnimations];
>获取对当前表示层的引用(即视图的状态,正是在此刻):
CALayer *currentLayer = self.subview.layer.presentationLayer;
>根据presentationLayer中的当前值重置变换(或框架或任何内容):
self.subview.layer.transform = currentLayer.transform;
>现在,从该变换(或框架或任何)到新值的动画:
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ self.subview.layer.transform = newTransform; } completion:NULL];
把这一切都放在一起,这里是一个例程,将我的变换缩放从2.0x切换到识别和返回:
- (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,然后返回:
- (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]; }
顺便说一句,虽然它对于真正快速的动画来说通常并不重要,但对于像您这样的慢速动画,您可能希望将反转动画的持续时间设置为与您当前动画中进展的距离相同例如,如果你在3.0秒的动画中有0.5秒,当你反转时,你可能不需要花费3.0秒才能扭转你迄今为止所做的一小部分动画,而仅仅是0.5秒).因此,这可能看起来像:
- (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,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]; }