如何暂停和恢复UIView动画?

4

我有一个UIView,上面有几个UILabel,正在从上到下动画,反之亦然。可以说是一种类似于Autoque的东西 :) 我使用两个函数:

-(void)goUp 
-(void)goDown 

这些函数会启动一个UIView动画到所需的位置。它们都定义了一个AnimationDidStopSelector,在结束时调用另一个函数。这一切都很顺利。

当触摸屏幕时,使用touchesBegan,我想暂停当前动画并使用touchesMoved事件更改UIView的垂直位置。在touchesEnded中,我想恢复动画到所需的结束位置。

正确的方法是什么?

Thomas


这是我发现最好的工作方式:http://stackoverflow.com/questions/9104487/how-to-pause-and-resume-uiview-animation-without-block-animation - John Riselvato
5个回答

7

我在UIView上创建了一个分类,用于暂停和停止动画:

@interface UIView (AnimationsHandler)

- (void)pauseAnimations;
- (void)resumeAnimations;

@end

@implementation UIView (AnimationsHandler)
- (void)pauseAnimations
{
    CFTimeInterval paused_time = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
    self.layer.speed = 0.0;
    self.layer.timeOffset = paused_time;
}

- (void)resumeAnimations
{
    CFTimeInterval paused_time = [self.layer timeOffset];
    self.layer.speed = 1.0f;
    self.layer.timeOffset = 0.0f;
    self.layer.beginTime = 0.0f;
    CFTimeInterval time_since_pause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - paused_time;
    self.layer.beginTime = time_since_pause;
}

建议在 resumeAnimations 中检查 paused_time 是否等于 0,以确保我们在暂停之前已经暂停了它。 - Cherpak Evgeny
这种方法似乎与UIPercentDrivenInteractiveTransition不兼容。 - Johan

4
实际上,根据 Vladimir 提供的问题的答案,您仍然可以暂停 UIView 动画,因为它会暂停我的 CABasicAnimations 和我在实现所有动画作为 CABasicaAnimations 后添加了一些 UIView 动画,我认为这些动画不会被暂停,但它们也没有起作用。这是相关链接
我想要暂停整个视图,所以我传递了 self.view.layer 作为要暂停的层。但对于那些不了解 CALayer 的人,传递您想要暂停的 view.layer。每个 UIView 都有一个 CALayer,所以只需传递与您相关的最上层的 view.layer。在 Thomas 的情况下,基于您自己的答案,似乎您想要传递 self.containerView.layer 进行暂停。
之所以能够这样做的原因是因为 UIView 动画只是 Core Animation 上面的一层。至少这是我的理解。
希望这可以帮助未来想知道如何暂停动画的人。

2

弗拉基米尔,有关于CAAnimations的问题很有意义..但我找到了一种方法来“暂停”,所以我可以继续使用UIView动画:

CALayer *pLayer = [self.containerView.layer presentationLayer];
CGRect frameStop = pLayer.frame;
pausedX = frameStop.origin.x;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.01];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];     
// set view properties

frameStop.origin.x = pausedX;
self.containerView.frame = frameStop;
[UIView commitAnimations];

我在这里使用presentationLayer来查找动画视图当前的x值。之后,我执行一个新的动画,覆盖原始动画。请确保为此设置setAnimationBeginsFromCurrentstate:YES。这将取消原始动画,并将动画视图放置在动画过程的当前位置,而不是其目标位置(它会自动执行)。希望这也能帮助其他人! :)

如果您将pausedX定义为int,则会自动转换为CGFloat。frameStop是CGRect,它是由CGSize和CGPoint组成的结构体。原点是由两个CGFloat组成的结构体。 - willc2
如果您正在对转换进行动画处理而不是帧,那么该如何实现呢? - zakdances

1

我不确定是否可以直接使用UIView,但您绝对可以通过动画视图的CALayer来实现。请参见此问题以了解有关暂停和恢复CAAnimations的信息。


0
希望这能对你有所帮助。
- (void)goUP{
    CFTimeInterval pausedTime = [self.layer timeOffset];
    self.layer.speed = 1.0;
    self.layer.timeOffset = 0.0;
    self.layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    self.layer.beginTime = timeSincePause;
}

- (void)goDown{
    CFTimeInterval pausedTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
    self.layer.speed = 0.0;
    self.layer.timeOffset = pausedTime;
}

当您调用“Layer animate”时,它将影响所有图层树和子模式图层动画。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接