UICollectionView performBatchUpdates:动画所有部分

Posted

技术标签:

【中文标题】UICollectionView performBatchUpdates:动画所有部分【英文标题】:UICollectionView performBatchUpdates: animates all sections 【发布时间】:2013-01-13 19:53:08 【问题描述】:

我正在编写一个自定义的UICollectionViewFlowLayout,我注意到当我在集合视图上调用performBatchUpdates:completion: 时,所有部分都会调用initialLayoutAttributesForAppearingItemAtIndexPath:initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath:。结果是 所有 部分都应用了动画,而不是 只是 新添加的部分。

[collectionView performBatchUpdates:^
    currentModelArrayIndex++;
    [collectionView insertSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex]];
    [collectionView reloadSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex-1]];
 completion:^(BOOL finished) 
    [collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:currentModelArrayIndex] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
];

到目前为止,我尝试的是删除对performBatchUpdates:completion: 的调用以代替简单的更新,但无论如何,已经存在的部分(所有部分)都是动画的。我想出了一个检查解决方案,以确保我正在更改 only 最后一部分的布局属性,但感觉很hacky。

if (decorationIndexPath.section == [(id<UICollectionViewDataSource>)self.collectionView.delegate numberOfSectionsInCollectionView:self.collectionView] - 1)

   layoutAttributes.alpha = 0.0f;
   layoutAttributes.transform3D = CATransform3DMakeTranslation(-CGRectGetWidth(layoutAttributes.frame), 0, 0);

这是只为某些部分设置动画的正确方法吗?

【问题讨论】:

【参考方案1】:

好的,我有答案了;它并没有比前一个漂亮很多,但它使布局不会接触数据源,所以它更干净。

基本上,我们需要覆盖prepareForCollectionViewUpdates:finalizeCollectionViewUpdates 以跟踪我们正在插入的部分。我有一个可变集合,其中包含我们要插入的部分的 NSNumber 实例。

-(void)prepareForCollectionViewUpdates:(NSArray *)updateItems

    [super prepareForCollectionViewUpdates:updateItems];

    [updateItems enumerateObjectsUsingBlock:^(UICollectionViewUpdateItem *updateItem, NSUInteger idx, BOOL *stop) 
        if (updateItem.updateAction == UICollectionUpdateActionInsert)
        
            [insertedSectionSet addObject:@(updateItem.indexPathAfterUpdate.section)];
        
    ];


-(void)finalizeCollectionViewUpdates

    [super finalizeCollectionViewUpdates];

    [insertedSectionSet removeAllObjects];

接下来,我在设置项目和装饰视图的初始布局属性时检查索引路径的部分是否包含在该集合中。

-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath

    UICollectionViewLayoutAttributes *layoutAttributes;

    if ([elementKind isEqualToString:AFCollectionViewFlowLayoutBackgroundDecoration])
    
        if ([insertedSectionSet containsObject:@(decorationIndexPath.section)])
        
            layoutAttributes = [self layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:decorationIndexPath];
            layoutAttributes.alpha = 0.0f;
            layoutAttributes.transform3D = CATransform3DMakeTranslation(-CGRectGetWidth(layoutAttributes.frame), 0, 0);
        
    

    return layoutAttributes;


-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath

    UICollectionViewLayoutAttributes *layoutAttributes;

    if ([insertedSectionSet containsObject:@(itemIndexPath.section)])
    
        layoutAttributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
        layoutAttributes.transform3D = CATransform3DMakeTranslation([self collectionViewContentSize].width, 0, 0);
    

    return layoutAttributes;

否则我会从这些方法中返回 nil,因为 nil 是默认值。

这还具有更好的旋转动画的额外好处。

【讨论】:

以上是关于UICollectionView performBatchUpdates:动画所有部分的主要内容,如果未能解决你的问题,请参考以下文章

-[UICollectionView _endItemAnimations] 中的 UICollectionView 断言失败

如何滚动另一个 UICollectionView 下方的 UICollectionView?

UICollectionView 单元内部已加载,但 UICollectionView 未显示

UICollectionView 断言失败 -[UICollectionView _updateWithItems:tentativelyForReordering:]

UITableviewCell 中的 UICollectionView。添加约束后,UICollectionView 不显示

将标题添加到 UICollectionView,而不是 UICollectionView 的部分