UICollectionView(3x3 Grid)与静态单元格分页

Posted

技术标签:

【中文标题】UICollectionView(3x3 Grid)与静态单元格分页【英文标题】:UICollectionView (3x3 Grid) paging with static cell 【发布时间】:2015-11-30 18:44:53 【问题描述】:

我有一个 3x3 网格布局中的 UICollectionView 显示图像。 UICollectionView 已将“pagingEnabled”设置为 YES,以便在具有 9 个图像的 3x3 网格的页面之间“分页”。 这是使用自定义 UICollectionViewLayout 完成的:

@implementation HorizontalCollectionViewLayout

- (instancetype)init

    self = [super init];
    if (self) 
    
    return self;


- (CGSize)collectionViewContentSize

    // We should return the content size. Lets do some math:

    NSInteger verticalItemsCount = (NSInteger)floorf(self.collectionView.bounds.size.height / self.itemSize.height);
    NSInteger horizontalItemsCount = (NSInteger)floorf(self.collectionView.bounds.size.width / self.itemSize.width);

    NSInteger itemsPerPage = verticalItemsCount * horizontalItemsCount;
    NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];
    NSInteger numberOfPages = (NSInteger)ceilf((CGFloat)numberOfItems / (CGFloat)itemsPerPage);

    CGSize size = self.collectionView.bounds.size;
    size.width = numberOfPages * self.collectionView.bounds.size.width;
    return size;


- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds

    return YES;


- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

    // Get all the attributes for the elements in the specified frame
    NSArray *allAttributesInRect = [super layoutAttributesForElementsInRect:rect];
    NSArray *attributesArray = [[NSArray alloc] initWithArray:allAttributesInRect copyItems:YES];

    NSInteger verticalItemsCount = (NSInteger)floorf(self.collectionView.bounds.size.height / self.itemSize.height);
    NSInteger horizontalItemsCount = (NSInteger)floorf(self.collectionView.bounds.size.width / self.itemSize.width);
    NSInteger itemsPerPage = verticalItemsCount * horizontalItemsCount;

    for (NSInteger i = 0; i < attributesArray.count; i++)         
        UICollectionViewLayoutAttributes *attributes = attributesArray[i]; 
        NSInteger currentPage = (NSInteger)floor((double)i / (double)itemsPerPage);
        NSInteger currentRow = (NSInteger)floor((double)(i - currentPage * itemsPerPage) / (double)horizontalItemsCount);
        NSInteger currentColumn = i % horizontalItemsCount;
        CGRect frame = attributes.frame;
        frame.origin.x = self.itemSize.width * currentColumn + currentPage * self.collectionView.bounds.size.width;
        frame.origin.y = self.itemSize.height * currentRow;

        CGRect f = UIEdgeInsetsInsetRect(frame, UIEdgeInsetsMake(2, 2, 5, 2));

        attributes.frame = f;

    
    return attributesArray;



@end

这是按预期工作的,因为它会在第一页包含 9 张图片时创建一个新页面。

然后我想要完成的是根据页数在索引 8、17、26、35 的网格右下角创建一个静态/固定的“下一页”按钮。 (如果 collectionview 只有 1 页,则索引 8 处的按钮,如果 collectionview 只有 2 页,则索引 8 和索引 17 处的按钮......等等)。图片和页面的数量可能会根据用户上传到应用程序的图片数量而有所不同。

下图说明了这个想法:

关于如何做到这一点的任何提示? "collectionView:itemForIndexPath:" 应该包含什么逻辑?

【问题讨论】:

您的问题是关于放入collectionView:itemForIndexPath: 的逻辑、在此特定单元格内创建图像的方式还是处理“最后一个单元格内的触摸”的方式? 抱歉没有具体说明。它主要与应该进入collectionView的逻辑有关:itemForIndexPath: 你的数据源是什么? NSArray?只有一节? 一个 NSArray,有一个部分。 【参考方案1】:

在您的 cellForItemAtIndexPath 中,查看 indexPath.item 中您有兴趣替换的数字,并为您的 [ > ] 按钮返回一个集合视图单元格。

集合视图的工作方式是您永远不会真正关心屏幕上的可见单元格(您的 UICollectionViewLayout 正在处理它)。您只为给定的 indexPath 返回一个单元格。

为这个 [ > ] 单元格创建一个专用的 UICollectionViewCell 子类,并使用它自己的重用标识符。它将简化您的代码,并且您无需触摸当前的图像单元格。

【讨论】:

谢谢。关于如何计算最后一个单元格 pr 的索引路径的任何想法。页。 (应该是按钮的索引)当我的数据源(一个 NSArray)的大小以及因此页数的大小可以变化时?从逻辑上讲,我可以说索引是 8、17、26 ...但我认为对索引进行硬编码是个坏主意。 由于您的 CollectionViewLayout 强制每页 9 个项目,我在想如果 ((indexPath.row + 1) % 9 == 0) 然后创建您的 [ > ] 单元格。

以上是关于UICollectionView(3x3 Grid)与静态单元格分页的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 UISearchBar 或 UISearchDisplayController 作为 UICollectionView 标头?

如何在 UICollectionview 中显示前 9 张图像?

数据结构与算法之深入解析“矩阵中的幻方”的求解思路与算法示例

在Grid-view中动态添加多个按钮

如何在 UICollectionView 中获取选中的 CollectionViewCell?

如何反转一个 3x3 矩阵,每个元素都是一个 3x3 矩阵?