使用 invalidateLayout 调用的高级 UICollectionView 动画
Posted
技术标签:
【中文标题】使用 invalidateLayout 调用的高级 UICollectionView 动画【英文标题】:Advanced UICollectionView animation using invalidateLayout calls 【发布时间】:2013-03-22 09:23:18 【问题描述】:UICollectionView Programming Guide 说:
除了动画插入、删除和移动操作之外, 您可以随时使布局无效并强制它重绘其 内容。使布局无效不会直接为项目设置动画; 当您使布局无效时,集合视图会显示项目 在他们新计算的位置没有动画。然而 使布局无效的行为会导致布局对象移动项目 明确地。在自定义布局中,您可以使用此行为来 定期定位单元格并创建动画效果。
我一直在尝试这样的事情,其中AnimationStep
是我的UICollectionViewFlowLayout
子类用来有条件地设置具有三阶段动画的图块位置的枚举:
-(void)update
[self animateLayoutAfterDelay:2.0 toStep:AnimationStepOne];
[self animateLayoutAfterDelay:4.0 toStep:AnimationStepTwo];
[self animateLayoutAfterDelay:6.0 toStep:AnimationStepThree];
-(void)animateLayoutAfterDelay:(NSTimeInterval)delay toStep:(MagazineLayoutAnimationStep)step
double delayInSeconds = delay;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
[UIView animateWithDuration:2.0 animations:^
self.layout.animationStep = step;
[self.layout invalidateLayout];
];
);
这会产生不可预知的影响。有些单元格以我期望的方式动画,有些单元格被隐藏和显示,或者只是出现在它们的新位置。我在单元格上放置了随机背景颜色,以查看这是否可能是 UICollectionView 回收单元格的效果,果然,有时确实如此。这解释了一些奇怪之处,但不是全部。
有人知道 Apple 希望我如何为单元格设置动画并移动它们吗?
(我需要这个,因为我的集合视图单元格往往会改变大小,并且我想要一个没有任何对角线移动的优美动画)。
【问题讨论】:
【参考方案1】:答案是使用中间布局。
[self.collectionView setCollectionViewLayout: layoutForStepOne animated:YES completion:^(BOOL finished)
[self.collectionView setCollectionViewLayout: layoutForStepTwo animated:YES completion:^(BOOL finished)
[self.collectionView setCollectionViewLayout: layoutForStepThree animated:YES];
];
];
【讨论】:
【参考方案2】:很简单:
创建一些 UICollectionViewLayout 的新实例并使用
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated
将 UICollectionView 上的布局设置为这个新的布局对象。确保对动画参数使用 YES。
编辑: 对于多阶段动画,我会尝试
performBatchUpdates:completion:
并将下一次更新放入完成块并重复。
【讨论】:
我已经改变了我这样做的方式,但如果它确实解决了我原来的问题,我希望能够接受这个答案。替换整个布局肯定会使制作多阶段动画变得更加困难,在该动画中引用原始位置以过渡到新位置?以上是关于使用 invalidateLayout 调用的高级 UICollectionView 动画的主要内容,如果未能解决你的问题,请参考以下文章
使用 invalidateLayout 加载数据后调整 UICollectionViewCell 的大小
invalidateLayout() 和 reloadData() 之间的区别
带有 invalidateSupplementaryElements 和 UICollectionViewLayoutInvalidationContext 的 invalidateLayout
UICollectionView invalidateLayout 不会在屏幕方向更改时触发 sizeForItem