动态集合视图单元格的顶部对齐方式应该相同

Posted

技术标签:

【中文标题】动态集合视图单元格的顶部对齐方式应该相同【英文标题】:Top alignment of dynamic collection view cells should be same 【发布时间】:2020-01-16 12:57:01 【问题描述】:

我们正在显示一个包含两个单元格的集合视图,并在每个集合视图单元格中显示标签(带有文本的动态)。

我们能够做到这一点

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes 

一行数据中的两个单元格居中对齐。我们可以让它顶部对齐吗?

示例: 假设有两个单元格,一个单元格中有 2 行文本,第二个单元格中有 4 行文本。 在这种情况下,这两个标签彼此居中对齐。我们可以让它们顶部对齐吗?

提前致谢, 拉姆

【问题讨论】:

你能提供截图吗? 更新了@jtouzy。你能看一下吗 【参考方案1】:

我使用AlignedCollectionViewFlowLayout 来快速解决问题。

https://github.com/mischa-hildebrand/AlignedCollectionViewFlowLayout

【讨论】:

【参考方案2】:

我有 aprx 相同的功能,所以我分享我在工作条件下所做的事情。如果您的要求稍有不同,则需要进行更多自定义。

对于代码解释,我建议您浏览答案最后一部分中提到的参考链接。


创建自定义 FlowLayout 类

class CustomLayout: UICollectionViewFlowLayout 

    private var computedContentSize: CGSize = .zero
    private var cellAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
     var array = [String]()

    override var collectionViewContentSize: CGSize 
        return computedContentSize
    

    override func prepare() 
        computedContentSize = .zero
        cellAttributes = [IndexPath: UICollectionViewLayoutAttributes]()

        var preY = 10
        var highY = 10

        for section in 0 ..< collectionView!.numberOfSections 
            var i = 0
            for item in 0 ..< collectionView!.numberOfItems(inSection: section) 
                let awidth =  Int((self.collectionView?.bounds.width)!) / 3 - 15
                let aheight = self.array[item].height(withConstrainedWidth: CGFloat(awidth), font: UIFont.systemFont(ofSize: 16)) + 20

                var aX = 10

                if item % 3 == 1 
                    aX = aX + 10 + awidth
                
                else if item % 3 == 2 
                    aX = aX + 20 + 2 * awidth
                
                else 
                    aX = 10
                    preY = highY
                

                if highY < preY + Int(aheight) 
                    highY = preY + Int(aheight) + 5
                

                let itemFrame = CGRect(x: aX, y: preY, width: awidth, height: Int(aheight))
                let indexPath = IndexPath(item: item, section: section)
                let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                attributes.frame = itemFrame

                cellAttributes[indexPath] = attributes
                i += 1
            
        

        computedContentSize = CGSize(width: (self.collectionView?.bounds.width)!,
                                     height: CGFloat(collectionView!.numberOfItems(inSection: 0) * 70))
    


    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? 
        var attributeList = [UICollectionViewLayoutAttributes]()

        for (_, attributes) in cellAttributes 
            if attributes.frame.intersects(rect) 
                attributeList.append(attributes)
            
        

        return attributeList
    

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? 
        return cellAttributes[indexPath]
    

MainViewController

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout 
    @IBOutlet weak var myColView: UICollectionView!

    var array = ["Hello", "Look Behind", "Gotta get there", "Hey buddy", "Earth is rotating around the sun", "Sky is blue", "Kill yourself", "Humble docters", "Lets make party tonight Lets make party tonight", "Lets play PUB-G", "Where are you?", "Love you Iron Man."]

    override func viewDidLoad() 
        super.viewDidLoad()
        let myLayout =  CustomLayout()
        myLayout.array = self.array
        myColView.collectionViewLayout = myLayout
    

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return array.count
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
        cell.myLabel.text = array[indexPath.row]
        cell.myLabel.layer.borderColor = UIColor.lightGray.cgColor
        cell.myLabel.layer.borderWidth = 1

        return cell

    

使用的扩展程序

extension String 
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat 
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)

        return ceil(boundingBox.height)
    

    func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat 
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)

        return ceil(boundingBox.width)
    

输出:

参考:

https://www.raywenderlich.com/4829472-uicollectionview-custom-layout-tutorial-pinterest https://www.netguru.com/codestories/practical-introduction-to-custom-uicollectionview-layouts https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts

【讨论】:

以上是关于动态集合视图单元格的顶部对齐方式应该相同的主要内容,如果未能解决你的问题,请参考以下文章

iOS UICollectionView:具有交替网格对齐的圆形视图的单元格

将两个元素与表格单元格的顶部和底部对齐

设置单元格的对齐方式

设置DataGridView单元格的文本对齐方式

UICollectionView 单元格未对齐

垂直自动布局两个视图,动态高度对齐顶部