2

我正在尝试使用具有不同宽度但高度恒定的单元格创建一个 UICollectionView。UICollectionView 有 3 行并水平滚动。

每个单元格应该在它右边的下一个单元格和下面的行之间有 8px。我已将此设置为 IB 中的最小间距。

当我将滚动设置为垂直时,以下代码有效,所有单元格都向左对齐,所有单元格之间的间距为 8px。但是,如果在水平滚动时使用此代码,则不起作用。

任何方向将不胜感激。

class HorizontalCollectionViewFlowLayout: UICollectionViewFlowLayout {

    override init(){
        super.init()
        scrollDirection = .horizontal
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        self.scrollDirection = .horizontal
    }

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

        var leftMargin = sectionInset.left
        var maxY: CGFloat = -1.0
        attributes?.forEach { layoutAttribute in
            if layoutAttribute.frame.origin.y >= maxY {
                leftMargin = sectionInset.left
            }

            layoutAttribute.frame.origin.x = leftMargin

            leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
            maxY = max(layoutAttribute.frame.maxY , maxY)
        }

        return attributes
    }

}

编辑:这是我想要实现的 UI。

在此处输入图像描述

4

1 回答 1

0

此代码适用于我scrollDirection = .horizontal

 import UIKit

class LeftAlignedHorizontalCollectionViewFlowLayout: UICollectionViewFlowLayout {
    
    required override init() {super.init(); common()}
        required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder); common()}
        
        private func common() {
            scrollDirection = .horizontal
            estimatedItemSize = UICollectionViewFlowLayout.automaticSize
            minimumLineSpacing = 10
            minimumInteritemSpacing = 8
        }
        
        override func layoutAttributesForElements(
                        in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            
            guard let att = super.layoutAttributesForElements(in:rect) else {return []}
            
            let group = att.group(by: {$0.frame.origin.y})
            
            var x: CGFloat = sectionInset.left
            
            for attr in group {
                x = sectionInset.left
                for a in attr.value {
                    if a.representedElementCategory != .cell { continue }
                    a.frame.origin.x = x
                    x += a.frame.width + minimumInteritemSpacing
                }
            }
            return att
        }
}

extension Array {
    func group<T: Hashable>(by key: (_ element: Element) -> T) -> [[Element]] {
        var categories: [T: [Element]] = [:]
        var groups = [[Element]]()
        for element in self {
            let key = key(element)
            if case nil = categories[key]?.append(element) {
                categories[key] = [element]
            }
        }
        categories.keys.forEach { key in
            if let group = categories[key] {
                groups.append(group)
            }
        }
        return groups
    }
}
于 2022-01-04T14:05:51.213 回答