水平滚动时如何左对齐 UICollectionViewCells?

Posted

技术标签:

【中文标题】水平滚动时如何左对齐 UICollectionViewCells?【英文标题】:How to left align UICollectionViewCells when scrolling horizontally? 【发布时间】:2018-07-26 11:34:43 【问题描述】:

我正在尝试创建一个 UICollectionView,其中的单元格具有不同的宽度但高度不变。 UICollectionView 有 3 行,水平滚动。

每个单元格应该在它右边的下一个单元格和下面的行之间有 8 像素。我已将此设置为 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。

【问题讨论】:

提供您想要实现的具体 UI? @Jaydeep 我附上了我的目标图片 我正需要您正在寻找的东西,您找到解决方案了吗?如果是,请在此处添加,谢谢! 【参考方案1】:

此代码适用于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
    

【讨论】:

以上是关于水平滚动时如何左对齐 UICollectionViewCells?的主要内容,如果未能解决你的问题,请参考以下文章

ExtJS 6 - 在快速水平滚动时,列标题和数据未正确对齐

水平 UIStackView - 如何对齐里面的项目,以便一个向左浮动,另一个在中心?

如何更改 UIScrollView 中的滚动方向?

可水平滚动的 TableView 的右列未完全显示

如何将内容水平居中对齐并固定在左侧?

RecyclerView 水平滚动对齐在中心