我有一个 UIScrollView 的子类,用于图像幻灯片放映,具有无限滚动和循环幻灯片放映功能。
我曾经以这种方式设置过渡动画:(因为我希望过渡速度更慢)
[UIView animateWithDuration:1.0
delay:0 options:(UIViewAnimationCurveEaseOut)
animations:^{
self.scrollView.contentOffset = newOffset;}
completion:NULL];
而且效果很好。
然后我看了 WWDC 2011 的讲座“Advanced Scrolling Techniques”,他们建议通过重写 layoutSubviews
来实现无限滚动。
所以我改变了我的实现并覆盖layoutSubviews
一旦我这样做了,过渡动画就停止工作了。
如果我注释掉我的自定义layoutSubviews - 它又可以工作了!
为什么?
如何在覆盖layoutSubviews的同时制作自己的滚动动画?
谢谢!
最佳答案
好的,我想我找到了问题,并且找到了可能的解决方案。
理解问题的关键是理解当你调用
[UIView animateWithDuration...]
您在动画 block 内更改的所有属性都会立即更改。它们不会随着动画实际执行(视觉上)而改变。
因此,就我而言,我将 contentOffset 设置为目标值。 此操作立即调用layoutSubviews。
在我的layoutSubviews实现中,我正在检查是否积累了足够的移动。如果是这样 - 我正在重新排列我的 ImageView,并将 contentOffset 设置为其初始值。一旦我这样做了,就不再有任何动画了,因为什么都没有改变!
- 动画内容偏移到 X:
- 调用 setContentOffset 到 X:
- 调用layoutSubview
- 将 contentOffset 设置回 Y! (重新排列 View 后)
- 调用layoutSubview
- 此时没有任何动画...
- 调用 setContentOffset 到 X:
可能的修复
我不确定这是否是正确的方法,但它确实有效。 所以我们需要做的是确保当我们处于动画 block 中间时,layoutSubviews 不会发生任何变化。
因此,我创建了一个名为 isAnimating 的 BOOL 实例变量,并在动画 block 中对其进行了适当的设置:
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];
}
}
它又可以工作了!
关于iphone - 带有自定义layoutSubviews的UIScrollView不再有动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9786869/