UICollectionView performBatchUpdates:为所有部分设置动画 [英] UICollectionView performBatchUpdates: animates all sections

查看:20
本文介绍了UICollectionView performBatchUpdates:为所有部分设置动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a custom UICollectionViewFlowLayout and I've noticed that initialLayoutAttributesForAppearingItemAtIndexPath: and initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath: will be called for all sections when I invoke performBatchUpdates:completion: on the collection view. The result is that all sections have the animation applied to them instead of just the newly added section.

[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.

What I've tried so far is removing the call to performBatchUpdates:completion: in lieu of simple updates, but the already existing sections (all of them) are animated in anyway. I've come up with a solution of checking to make sure that I'm changing the layout attributes of only the last section, but it feels 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);
}

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

Is this the proper way to go about animating only some sections?

推荐答案

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

OK, I've got an answer; it's not a lot prettier than the previous one, but it keeps the layout from touching the datasource, so it's cleaner.

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

Basically, we need to override prepareForCollectionViewUpdates: and finalizeCollectionViewUpdates to keep track of the sections that we're inserting. I have a mutable set that contains NSNumber instances of the sections that we're inserting.

-(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];
}

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

Next, I check to see if the index path's section is included in that set when setting the initial layout attributes for items and decoration views.

-(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 是默认值.

I'm returning nil from these methods otherwise because nil is the default value.

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

This has the added benefit of having nicer rotation animations, as well.

这篇关于UICollectionView performBatchUpdates:为所有部分设置动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆