You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义UICollectionView布局下实现数据3行水平排列展示

实现UICollectionView 3行水平排列居中方案

你当前使用的UICollectionViewCenterLayout是基于垂直流布局的扩展,默认是垂直滚动按行排列元素。要实现6个元素3行水平排列、支持横向滚动且保留居中效果,按以下步骤调整即可:

第一步:基础配置调整

在初始化布局的位置先修改基础属性:

  • 把布局的滚动方向改为水平
  • 固定每行放2个元素(6个元素刚好占满3行),统一设置cell尺寸、间距参数
  • 按需开启分页效果,横向滚动时如果需要整页翻页可以开启isPagingEnabled
// 布局初始化配置示例
let layout = UICollectionViewCenterHorizontalLayout()
layout.scrollDirection = .horizontal
// 按实际设计需求调整cell尺寸
layout.itemSize = CGSize(width: 160, height: 80)
layout.minimumLineSpacing = 12 // 列与列之间的水平间距
layout.minimumInteritemSpacing = 15 // 同一列上下元素的垂直间距
layout.sectionInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
collectionView.collectionViewLayout = layout
// 不需要整页滚动可删除下面一行
collectionView.isPagingEnabled = true

第二步:修改自定义布局适配水平滚动

把原来适配垂直布局的逻辑调整为适配水平滚动的逻辑,完整代码如下:

class CollectionViewColumn {
    var attributes = [UICollectionViewLayoutAttributes]()
    var spacing: CGFloat = 0

    init(spacing: CGFloat) {
        self.spacing = spacing
    }

    func add(attribute: UICollectionViewLayoutAttributes) {
        attributes.append(attribute)
    }

    // 计算单列总高度
    var columnHeight: CGFloat {
        return attributes.reduce(0, { result, attribute -> CGFloat in
            return result + attribute.frame.height
        }) + CGFloat(attributes.count - 1) * spacing
    }

    // 单列元素垂直居中
    func centerLayout(collectionViewHeight: CGFloat) {
        let padding = (collectionViewHeight - columnHeight) / 2
        var offset = padding
        for attribute in attributes {
            attribute.frame.origin.y = offset
            offset += attribute.frame.height + spacing
        }
    }
}

class UICollectionViewCenterHorizontalLayout: UICollectionViewFlowLayout {
    // 固定每行元素数量,2个元素一行刚好6个元素占3行
    private let itemCountPerRow = 2

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributes = super.layoutAttributesForElements(in: rect) else {
            return nil
        }

        var columns = [CollectionViewColumn]()
        var currentColumnX: CGFloat = -1

        for attribute in attributes {
            // 水平滚动时X轴中点相同的元素属于同一列
            if currentColumnX != attribute.frame.midX {
                currentColumnX = attribute.frame.midX
                columns.append(CollectionViewColumn(spacing: minimumInteritemSpacing))
            }
            columns.last?.add(attribute: attribute)
        }

        // 每列元素做垂直居中调整
        columns.forEach { $0.centerLayout(collectionViewHeight: collectionView?.frame.height ?? 0) }
        return columns.flatMap { $0.attributes }
    }

    // 重写内容尺寸保证滚动范围正确
    override var collectionViewContentSize: CGSize {
        guard let collectionView = collectionView else { return .zero }
        let totalItemCount = collectionView.numberOfItems(inSection: 0)
        // 计算总列数:总元素数/每行元素数,向上取整
        let totalColumn = Int(ceil(Double(totalItemCount) / Double(itemCountPerRow)))
        let contentWidth = CGFloat(totalColumn) * (itemSize.width + minimumLineSpacing) + sectionInset.left + sectionInset.right - minimumLineSpacing
        let contentHeight = collectionView.bounds.height
        return CGSize(width: contentWidth, height: contentHeight)
    }
}

注意事项

  • 如果cell尺寸不固定,需要在collectionView(_:layout:sizeForItemAt:)代理方法中返回对应cell的实际尺寸
  • 后续元素数量变动时,只要调整itemCountPerRow的数值即可适配不同行数要求
  • 代码中间距参数可根据设计需求自行调整,和原有居中逻辑保持一致,仅适配了水平滚动场景

内容的提问来源于stack exchange,提问作者Vijay Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:45:03