4

简短的问题:

有没有办法在performBatchUpdates:块中添加和删除补充视图,如单元格和部分,类似于insertItemsAtIndexPaths: deleteItemsAtIndexPaths:甚至reloadItemsAtIndexPaths:方法?

长解释:

我使用UICollectionViewwith 部分。单元格像网格一样布置,每行最多可以有 6 个单元格。如果单元格的总数没有填满一个部分的所有行,我会添加额外的补充视图。额外的补充视图只是填补了空白。所以结果应该是每个部分都完全填充了所有可用的单元格,并且(可能的)剩余的空白点填充了补充视图。所以每行有 6 个视觉元素,一个单元格或一个补充视图。

为了实现这一点,我UICollectionViewFlowLayout使用以下实现实现了一个基于自定义的布局prepareLayout:

- (void)prepareLayout {
    [super prepareLayout];

    self.supplementaryViewAttributeList = [NSMutableArray array];
    if(self.collectionView != nil) {
        // calculate layout values
        CGFloat contentWidth = self.collectionViewContentSize.width - self.sectionInset.left - self.sectionInset.right;
        CGFloat cellSizeWithSpacing = self.itemSize.width + self.minimumInteritemSpacing;
        NSInteger numberOfItemsPerLine = floor(contentWidth / cellSizeWithSpacing);
        CGFloat realInterItemSpacing = (contentWidth - (numberOfItemsPerLine * self.itemSize.width)) / (numberOfItemsPerLine - 1);

        // add supplementary attributes
        for (NSInteger numberOfSection = 0; numberOfSection < self.collectionView.numberOfSections; numberOfSection++) {
            NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:numberOfSection];
            NSInteger numberOfSupplementaryViews = numberOfItemsPerLine - (numberOfItems % numberOfItemsPerLine);

            if (numberOfSupplementaryViews > 0 && numberOfSupplementaryViews < 6) {
                NSIndexPath *indexPathOfLastCellOfSection = [NSIndexPath indexPathForItem:(numberOfItems - 1) inSection:numberOfSection];
                UICollectionViewLayoutAttributes *layoutAttributesOfLastCellOfSection = [self layoutAttributesForItemAtIndexPath:indexPathOfLastCellOfSection];

                for (NSInteger numberOfSupplementor = 0; numberOfSupplementor < numberOfSupplementaryViews; numberOfSupplementor++) {
                    NSIndexPath *indexPathOfSupplementor = [NSIndexPath indexPathForItem:(numberOfItems + numberOfSupplementor) inSection:numberOfSection];
                    UICollectionViewLayoutAttributes *supplementaryLayoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:ARNCollectionElementKindFocusGuide withIndexPath:indexPathOfSupplementor];
                    supplementaryLayoutAttributes.frame = CGRectMake(layoutAttributesOfLastCellOfSection.frame.origin.x + ((numberOfSupplementor + 1) * (self.itemSize.width + realInterItemSpacing)), layoutAttributesOfLastCellOfSection.frame.origin.y, self.itemSize.width, self.itemSize.height);
                    supplementaryLayoutAttributes.zIndex = -1;

                    [self.supplementaryViewAttributeList addObject:supplementaryLayoutAttributes];
                }
            }
        }
    }
}

如果从一开始所有数据都可用并且数据没有更改,则此方法非常有用。但是,如果在生命周期内添加和删除数据,它就会惨遭失败。performBatchUpdates:在补充视图中插入和删除单元格。

应该发生什么:

对于与insertItemsAtIndexPaths:补充视图同时插入的每个单元格,indexPath都应删除。此外,对于使用新补充视图删除的每个单元格,deleteItemsAtIndexPaths:应同时添加indexPath

问题:

调用我的prepareLayout:布局并计算正确的layoutAttributes. 但layoutAttributesForSupplementaryViewOfKind:atIndexPath:被称为怪异indexPaths。特别是从数组中删除layoutAttributesForSupplementaryViewOfKind:atIndexPath:的 old 被调用!indexPathssupplementaryViewAttributeList

例子:

在插入新单元格的情况下,prepareLayout:正确删除layoutAttributes,但layoutAttributesForSupplementaryViewOfKind:atIndexPath: 仍然会调用不再可用和删除的 indexPath!仅此而已。indexPath对于所有其他补充观点,没有额外的要求。

为什么layoutAttributesForSupplementaryViewOfKind:atIndexPath:要求indexPaths不再可用?如何正确删除、插入或重新加载补充视图?我想念什么?

来源:

完整的来源可以在这里找到:

自定义布局:https ://github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/layout/ARNCollectionViewFocusGuideFlowLayout.m

CollectionView 控制器: https ://github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/view-controllers/ARNMovieOverviewController.m (performBatchUpdates:在类的最后一个方法中)

4

2 回答 2

3

您的评论对我来说不是诀窍,我找到了另一段代码并添加了它并且它有效,甚至删除了上述建议,它仍然有效。集合视图当然很强大,但忘记了一个功能,比如这个......

- (NSArray<NSIndexPath *>   *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind
{
    return self.removedIndexPaths;
}

事情可能会出错。

于 2016-07-10T07:51:36.883 回答
1

一种解决方案是将 a 添加[[collectionView collectionViewLayout] invalidateLayout]performBatchUpdates:块中。这会强制布局重新计算并删除无效的 indexPaths。

于 2016-06-24T15:55:40.667 回答