ios - UICollectionView补充 View 如何正确插入或删除

标签 ios objective-c uicollectionview uicollectionviewlayout uicollectionreusableview

简短的问题:

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

详细解释:

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

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

- (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: 中插入和删除单元格会打乱补充 View 。

应该发生什么:

对于使用 insertItemsAtIndexPaths: 插入的每个单元格,应删除相同 indexPath 处的补充 View 。此外,对于使用 deleteItemsAtIndexPaths: 删除的每个单元格,应在相同的 indexPath 中添加一个新的补充 View 。

问题:

我的布局的 prepareLayout: 被调用并计算出正确的 layoutAttributes。但是 layoutAttributesForSupplementaryViewOfKind:atIndexPath: 被调用用于奇怪的 indexPaths。特别是 layoutAttributesForSupplementaryViewOfKind:atIndexPath: 被调用用于从 supplementaryViewAttributeList 数组中删除的旧 indexPaths!

示例:

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

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

来源:

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

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

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

最佳答案

您的评论对我没有用,我找到了另一段代码并添加了它并且它有效,甚至删除了上述建议,它仍然有效。 Collection View 当然很强大,但是忘记了像这个这样的功能......

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

事情可能会变得相当糟糕。

关于ios - UICollectionView补充 View 如何正确插入或删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36386854/

相关文章:

ios - 在状态恢复期间显示应用程序屏幕快照而不是启动屏幕

ios - objectForKey 在 Swift 中为 NSUserDefaults 返回 nil

ios - 从 TableView 中删除行 | NSUserDefaults + NSKeyedArchiver

ios - 将现有图像替换为相册

ios - 有什么方法可以连续为 Collection View 单元格调用 initialLayoutAttributesForAppearingItemAtIndexPath 并延迟一些?

ios - 如何调整 UITextField 占位符文本大小以适合 UITextField 宽度?

objective-c - NSFileHandle -readDataOfLength : return autoreleased NSData? 是否

objective-c - iOS应用程序在后台崩溃并快速重新启动,没有崩溃日志

ios - 是否可以将 UICollectionView 中的滚动限制为集合中项目的子集?

ios - 在 UICollectionViewCell 中获取图像