具有自定义layoutSubviews的UIScrollView不再动画

时间:2012-03-20 12:35:11

标签: iphone ios uiscrollview uikit layoutsubviews

我有一个UIScrollView的子类,我用它来进行图像幻灯片放映,无限滚动和圆形幻灯片放映。

我曾经以这种方式为转换设置动画:(因为我希望转换更慢)

[UIView animateWithDuration:1.0 
                      delay:0 options:(UIViewAnimationCurveEaseOut)
                 animations:^{
                         self.scrollView.contentOffset = newOffset;}
                 completion:NULL];

它运作得很好。

然后我观看了WWDC 2011的“高级滚动技术”讲座,他们建议通过覆盖layoutSubviews来实现无限滚动。

所以我改变了我的实现并覆盖了layoutSubviews

一旦我这样做,过渡动画就停止了工作。

如果我注释掉我的自定义layoutSubviews - 它再次正常工作!

为什么?

在覆盖layoutSubviews时,如何制作自己的滚动动画?

谢谢!

1 个答案:

答案 0 :(得分:3)

好的,我想我发现了问题,并且可能已经解决了。

理解问题的关键是了解当你打电话时

[UIView animateWithDuration...]

您在动画块中更改的所有属性都会立即更改 。它们不会随着动画实际执行而发生变化(视觉上)。

所以在我的情况下,我将contentOffset设置为我的目标值。 此操作立即调用layoutSubviews。

在我的layoutSubviews实现中,我正在检查是否已经积累了足够的移动。如果是这样 - 我正在重新排列我的ImageViews,并将contentOffset设置为其初始值。一旦我这样做,就没有什么可以动画了,因为没有任何改变!

  1. 将contentOffset动画为X:
    • 将setContentOffset调用到X:
      • 调用layoutSubview
        • 将contentOffset设置回Y! (重新安排意见后)
    • 此时没有任何动画......
  2. 可能的修复

    我不确定这是否是正确的方法,但它的工作正常。 所以我们需要做的是确保在动画块中间不会对layoutSubviews进行任何更改。

    所以我创建了一个名为isAnimating的BOOL实例变量,并在动画块中正确设置:

    self.isAnimating = YES;
    [UIView animateWithDuration:self.transitionDuration 
                          delay:0 
                        options:(UIViewAnimationOptionCurveEaseOut) 
                     animations:^{
        self.contentOffset = newOffset;
    }
    
                     completion:^(BOOL finished) {
            self.isAnimating = NO;
            [self setNeedsLayout];
    }];
    

    现在在layoutSubviews中我们需要考虑isAnimating:

    -(void) layoutSubviews
    {
        [super layoutSubviews];
        if (self.isAnimating == NO)
        {
            [self rearrangeIfNecessary];
        }
    }
    

    它又恢复了工作!