Ios UICollectionView列上的垂直偏移

Ios UICollectionView列上的垂直偏移,ios,swift,uicollectionview,interface-builder,Ios,Swift,Uicollectionview,Interface Builder,右边的图片是我想要达到的 有人知道我如何在两列UICollectionView上实现这一点吗? 我可以通过测试if(indexPath.row%2=0)来识别我的列,但我无法实现这个结果 这是一个简单的方法吗?或者我需要自定义UICollectionViewFlowLayout吗 注意:我的所有单元格大小相同。是的,您需要创建一个自定义的UICollectionViewLayout,这很容易实现。您只需要以下内容: :执行提供布局信息所需的前期计算 :返回基于初始计算的整个内容区域的总大小

右边的图片是我想要达到的

有人知道我如何在两列UICollectionView上实现这一点吗? 我可以通过测试if(indexPath.row%2=0)来识别我的列,但我无法实现这个结果

这是一个简单的方法吗?或者我需要自定义UICollectionViewFlowLayout吗


注意:我的所有单元格大小相同。

是的,您需要创建一个自定义的
UICollectionViewLayout
,这很容易实现。您只需要以下内容:

  • :执行提供布局信息所需的前期计算

  • :返回基于初始计算的整个内容区域的总大小

  • :返回指定矩形中的单元格和视图的属性

  • 现在我们有了同样大小的细胞,这很容易实现

    让我们声明几个要使用的变量:

        // Adjust this as you need
        fileprivate var offset: CGFloat = 50
    
        //    Properties for configuring the layout: the number of columns and the cell padding.
        fileprivate var numberOfColumns = 2
        fileprivate var cellPadding: CGFloat = 10
    
        //    Cache the calculated attributes. When you call prepare(), you’ll calculate the attributes for all items and add them to the cache. You can be efficient and 
        fileprivate var cache = [UICollectionViewLayoutAttributes]()
    
        //    Properties to store the content size.
        fileprivate var contentHeight: CGFloat = 0
        fileprivate var contentWidth: CGFloat {
            guard let collectionView = collectionView else {
                return 0
            }
            let insets = collectionView.contentInset
            return collectionView.bounds.width - (insets.left + insets.right)
        }
    
    接下来,让我们重写
    prepare()
    方法

        override func prepare() {
            // If cache is empty and the collection view exists – calculate the layout attributes
            guard cache.isEmpty == true, let collectionView = collectionView else {
                return
            }
    
            // xOffset: array with the x-coordinate for every column based on the column widths
            // yOffset: array with the y-position for every column, Using odd-even logic to push the even cell upwards and odd cells down.
            let columnWidth = contentWidth / CGFloat(numberOfColumns)
            var xOffset = [CGFloat]()
            for column in 0 ..< numberOfColumns {
                xOffset.append(CGFloat(column) * columnWidth)
            }
            var column = 0
    
            var yOffset = [CGFloat]()
            for i in 0..<numberOfColumns {
                yOffset.append((i % 2 == 0) ? 0 : offset)
            }
    
            for item in 0 ..< collectionView.numberOfItems(inSection: 0) {
    
                let indexPath = IndexPath(item: item, section: 0)
    
                // Calculate insetFrame that can be set to the attribute
                let cellHeight = columnWidth - (cellPadding * 2)
                let height = cellPadding * 2 + cellHeight
                let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height)
                let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
    
                // Create an instance of UICollectionViewLayoutAttribute, sets its frame using insetFrame and appends the attributes to cache.
                let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                attributes.frame = insetFrame
                cache.append(attributes)
    
                // Update the contentHeight to account for the frame of the newly calculated item. It then advances the yOffset for the current column based on the frame
                contentHeight = max(contentHeight, frame.maxY)
                yOffset[column] = yOffset[column] + height
    
                column = column < (numberOfColumns - 1) ? (column + 1) : 0
            }
        }
    
    你可以在课堂上找到答案

    它是这样出现的:

    注意:这只是一个演示,您可能需要根据需要进行调整


    希望有帮助

    我认为您应该自定义
    UICollectionViewFlowLayout
    。或者你可以看看这个令人印象深刻的!这真的很有帮助,谢谢你!!!我可以问您如何减少两列之间和两行之间的间距吗?您可以公开
    单元格填充
    来调整填充。我相信使用协议和代理通常是最好的方法。
        //    Using contentWidth and contentHeight from previous steps, calculate collectionViewContentSize.
        override var collectionViewContentSize: CGSize {
            return CGSize(width: contentWidth, height: contentHeight)
        }
    
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
            var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
    
            for attributes in cache {
                if attributes.frame.intersects(rect) {
                    visibleLayoutAttributes.append(attributes)
                }
            }
            return visibleLayoutAttributes
        }
    
        override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            return cache[indexPath.item]
        }