将UICollectionView创建为两行的水平菜单

问题描述 投票:0回答:1

我正在尝试将UICollectionView设置为两行的水平菜单

我试图提供标签尺寸。但是缩进太多。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let tagName = tags[indexPath.row].tag?.name ?? ""
        let size: CGSize = tagName.size(withAttributes: [.font: UIFont.systemFont(ofSize: 13)])
        return CGSize(width: size.width + 52, height: 34)
}

此代码给了我很多缩进:

我需要这样的最终结果:

[ⅩⅩⅩⅩ] [XXXXXXXXX] [XXXXXXXXXX] [XXXXXX]

[XXXXXXXXX] [XXXXXXXX] [XXXXXX] [XXX]

ios swift uicollectionview horizontal-scrolling
1个回答
0
投票

我找到了解决方案。根据列的宽度为每列声明xOffset数组并用其x坐标填充。 yOffset数组跟踪每一列的y位置。

protocol SelfSizingHorizontallyCustomLayoutDelegate: AnyObject {
    func collectionView(_ collectionView: UICollectionView, widthForCellAtIndexPath indexPath: IndexPath) -> CGFloat
}

class SelfSizingHorizontallyCustomLayout: UICollectionViewLayout {
    weak var delegate: SelfSizingHorizontallyCustomLayoutDelegate?

    private let numberOfColumns = 2
    private let cellPadding: CGFloat = 6
    private var cache: [UICollectionViewLayoutAttributes] = []
    private var contentWidth: CGFloat = 0

    private var contentHeight: CGFloat {
        guard let collectionView = collectionView else {
            return 0
        }
        let insets = collectionView.contentInset
        return collectionView.bounds.height - (insets.top + insets.bottom)
    }
    override var collectionViewContentSize: CGSize {
        return CGSize(width: contentWidth, height: contentHeight)
    }

    override func prepare() {
        guard cache.isEmpty, let collectionView = collectionView else { return }

        let columnHeight = contentHeight / CGFloat(numberOfColumns)
        var yOffset: [CGFloat] = []
        for column in 0..<numberOfColumns {
            yOffset.append(CGFloat(column) * columnHeight)
        }

        var column = 0
        var xOffset: [CGFloat] = .init(repeating: 0, count: numberOfColumns)

        for item in 0..<collectionView.numberOfItems(inSection: 0) {
            let indexPath = IndexPath(item: item, section: 0)

            let cellWidth = delegate?.collectionView(collectionView, widthForCellAtIndexPath: indexPath) ?? 180
            let width = cellPadding * 2 + cellWidth
            let frame = CGRect(x: xOffset[column], y: yOffset[column], width: width, height: columnHeight)
            let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)

            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = insetFrame
            cache.append(attributes)

            contentWidth = max(contentWidth, frame.maxX)
            xOffset[column] = xOffset[column] + width
            column = column < (numberOfColumns - 1) ? (column + 1) : 0
        }
    }

    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]
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.