UICollection View Flow Layout Vertical Align

后端 未结 10 2140
無奈伤痛
無奈伤痛 2021-02-03 21:45

By default, when you are using the flow layout in a collection view, cells are centered vertically. Is there a way to change this alignment ?

10条回答
  •  别那么骄傲
    2021-02-03 22:11

    I have used something similar to the before answers. In my case I want to align cells by colum with different heights.

    import UIKit
    
    class AlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
    
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            if let attributes = super.layoutAttributesForElements(in: rect) {
                let sectionElements: [Int : [UICollectionViewLayoutAttributes]] = attributes
                    .filter {
                        return $0.representedElementCategory == .cell //take cells only
                    }.groupBy {
                        return $0.indexPath.section //group attributes by section
                }
    
                sectionElements.forEach { (section, elements) in
                    //get suplementary view (header) to align each section
                    let suplementaryView = attributes.first {
                        return $0.representedElementCategory == .supplementaryView && $0.indexPath.section == section
                    }
                    //call align method
                    alignToTopSameSectionElements(elements, with: suplementaryView)
                }
    
                return attributes
            }
    
            return super.layoutAttributesForElements(in: rect)
        }
    
        private func alignToTopSameSectionElements(_ elements: [UICollectionViewLayoutAttributes], with suplementaryView: UICollectionViewLayoutAttributes?) {
            //group attributes by colum 
            let columElements: [Int : [UICollectionViewLayoutAttributes]] = elements.groupBy {
                return Int($0.frame.midX)
            }
    
            columElements.enumerated().forEach { (columIndex, object) in
                let columElement = object.value.sorted {
                    return $0.indexPath < $1.indexPath
                }
    
                columElement.enumerated().forEach { (index, element) in
                    var frame = element.frame
    
                    if columIndex == 0 {
                        frame.origin.x = minimumLineSpacing
                    }
    
                    switch index {
                    case 0:
                        if let suplementaryView = suplementaryView {
                            frame.origin.y = suplementaryView.frame.maxY
                        }
                    default:
                        let beforeElement = columElement[index-1]
                        frame.origin.y = beforeElement.frame.maxY + minimumInteritemSpacing
                    }
    
                    element.frame = frame
                }
            }
        }
    }
    
    public extension Array {
    
        func groupBy  (groupingFunction group: (Element) -> U) -> [U: Array] {
    
            var result = [U: Array]()
    
            for item in self {
    
                let groupKey = group(item)
    
                if result.has(groupKey) {
                    result[groupKey]! += [item]
                } else {
                    result[groupKey] = [item]
                }
            }
    
            return result
        }
    }
    

    This is the result of this layout:

提交回复
热议问题