1

有很多类似的问题,但它们都与这个不同。

我有UIScrollView它可以以编程方式滚动和停止。

我通过以下代码滚动:

[UIView animateWithDuration:3
                              delay:0
                            options:UIViewAnimationOptionCurveEaseInOut
                         animations:^{ [self.scrollView scrollRectToVisible:newPageRect animated:NO]; }];

而且我根本不知道如何阻止它。在所有情况下,它都不会停止或将停止但它也会跳转到newPageRect(例如在 的情况下removeAllAnimations)。

你能建议如何正确停止它吗?我是否应该更改我的代码以滚动到另一个代码?

4

1 回答 1

1

我认为这是你最好自己做的事情。创建一个适当的库来为数据设置动画可能需要几个小时,但最终它会是非常有益的。

需要几个组件:

有时间限制的动画应该包括 aCADispalyLink或 a NSTimer。创建一个公共方法,例如animateWithDuration:它将启动计时器、记录当前日期并设置目标日期。插入一个浮点值作为属性,然后将其从 0 插入到 1 到日期。很可能看起来像这样:

- (void)onTimer {
    NSDate *currentTime = [NSDate date];
    CGFloat interpolation = [currentTime timeIntervalSinceDate:self.startTime]/[self.targetTime timeIntervalSinceDate:self.startTime];

    if(interpolation < .0f) { // this could happen if delay is implemented and start time may actually be larger then current
        self.currentValue = .0f;
    }
    else if(interpolation > 1.0f) { // The animation has ended
        self.currentValue = 1.0f;
        [self.displayLink invalidate]; // stop the animation
        // TODO: notify owner that the animation has ended
    }
    else {
        self.currentValue = interpolation;
        // TODO: notify owner of change made
    }
}

正如您从评论中看到的那样,您应该在此方法中再调用 2 次,这将通知所有者/侦听器动画的更改。这可以通过委托、块、调用、目标选择器对来实现……

所以此时你有一个在 0 和 1 之间插值的浮点值,现在可以用来插值你想要可见的矩形。这是一个非常简单的方法:

- (CGRect)interpolateRect:(CGRect)source to:(CGRect)target withScale:(CGFloat)scale
{
    return CGRectMake(source.origin.x + (target.origin.x-source.origin.x)*scale,
                      source.origin.y + (target.origin.y-source.origin.y)*scale,
                      source.size.width + (target.size.width-source.size.width)*scale,
                      source.size.height + (target.size.height-source.size.height)*scale);
}

所以现在把它们放在一起,它看起来像这样:

- (void)animateVisibleRectTo:(CGRect)frame {
    CGRect source = self.scrollView.visibleRect;
    CGRect target = frame;
    [self.animator animateWithDuration:.5 block:^(CGFloat scale, BOOL didFinish) {
        CGRect interpolatedFrame = [Interpolator interpolateRect:source to:target withScale:scale];
        [self.scrollView scrollRectToVisible:interpolatedFrame animated:NO];
    }];
}

这可能是一个很棒的系统,当您想要为不可动画的东西制作动画或只是对动画有更好的控制时,可以在很多系统中使用它。您可以添加stop需要使计时器失效或显示链接并通知所有者的方法。

您需要注意的不是创建保留周期。如果一个类保留了 animator 对象,而 animator 对象保留了侦听器(类),您将创建一个保留循环。

同样作为奖励,您可以通过计算更大的开始时间来轻松实现动画的其他属性,例如延迟。您可以创建任何类型的曲线,例如缓入、缓出,通过使用适当的函数来计算currentValue实例self.currentValue = pow(interpolation, 1.4)将很像缓入。的幂1.0/1.4将是相同版本的缓出。

于 2015-06-12T13:25:50.690 回答