【问题标题】:Autoresize UICollectionView cells, Align cell to top自动调整 UICollectionView 单元格大小,将单元格对齐到顶部
【发布时间】:2020-07-07 06:00:27
【问题描述】:

我有一个 UICollectionView,有多个部分和行。 必要时固定大小的页眉和页脚视图。 可自动调整大小的单元格

单元格视图的设计如下:

绿色 - ImageView

橙色 - 带有numberOfLines = 0 的标签。

单元格应根据标签numberOfLines扩大其大小。

我在 MyCustomCell 中使用此代码实现了这一点:

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
        super.apply(layoutAttributes)
        let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)
        let targetSize = CGSize(width: Constants.screenWidth/3.5, height: 0)
        let autoLayoutSize = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: UILayoutPriority.required, verticalFittingPriority: UILayoutPriority.defaultLow)
        let autoLayoutFrame = CGRect(origin: autoLayoutAttributes.frame.origin, size: autoLayoutSize)
        autoLayoutAttributes.frame = autoLayoutFrame
        return autoLayoutAttributes
    }

单元格会自动调整大小,但 contentView(青色)垂直和水平居中对齐。

I need to make it vertically align to Top.

我也遇到了页眉和页脚的对齐问题。为此,我将 UICollectionViewFlowLayout 子类化了


class MainCollectionViewFlowLayout: UICollectionViewFlowLayout {

    override func invalidationContext(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutInvalidationContext {

        let context: UICollectionViewLayoutInvalidationContext = super.invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes)

        let indexPath = preferredAttributes.indexPath
        context.invalidateSupplementaryElements(ofKind: UICollectionView.elementKindSectionFooter, at: [indexPath])
        context.invalidateSupplementaryElements(ofKind: UICollectionView.elementKindSectionHeader, at: [indexPath])

        return context
    }

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

        var topMargin = sectionInset.top
        var leftMargin = sectionInset.left
        var maxY: CGFloat = -1.0
        attributes?.forEach { layoutAttribute in
            guard layoutAttribute.representedElementCategory == .cell else {
                return
            }

            if layoutAttribute.frame.origin.y >= maxY {
                leftMargin = sectionInset.left
                topMargin = sectionInset.top
            }

            layoutAttribute.frame.origin.x = leftMargin

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

        return attributes
    }

}

这是一张图片来说明当前的情况。青色是单元格的内容视图。我必须让它与顶部对齐。

编辑: 所以我意识到UICollectionViewFlowLayout 代码造成的错误比修复问题更多。我添加了layoutAttributesForElements 左对齐我的单元格,以防只有一个单元格。它实际上所做的是将我所有的单元格对齐到左边。 将代码修改为


class MainCollectionViewFlowLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

        let attributes = super.layoutAttributesForElements(in: rect)

        if attributes?.count == 1 {

            if let currentAttribute = attributes?.first {
                currentAttribute.frame = CGRect(x: self.sectionInset.left, y: currentAttribute.frame.origin.y, width: currentAttribute.frame.size.width, height: currentAttribute.frame.size.height)
            }
        }
        return attributes
    }
}

现在我的UICollectionViewCell 已正确对齐到水平中心,但只有一个单元格会左对齐。

垂直对齐仍然没有解决方案。

【问题讨论】:

    标签: ios swift uicollectionview flowlayout uicollectionviewflowlayout


    【解决方案1】:

    所以我在这个问题上做了很多工作。堆栈溢出帮助没有任何答案。所以我玩了自定义UICollectionViewFlowLayout方法layoutAttributesForElements

    此方法将调用每个部分,并将 layoutAttributesForElements 用于矩形。这将给出一个 UICollectionViewLayoutAttributes 数组,可以根据需要进行修改。

    我在确定要为我的单元格更改的 y 坐标时遇到问题。

    首先在layoutAttributesForElements 的属性中循环,我得到了标题并将它的高度保存在一个变量中。然后将单元格的其余部分 y 坐标更改为 headerHeight 值。

    不确定这是否正确,也没有进行任何性能测试。现在一切似乎都很好,没有任何延迟或抖动。

    这里是完整代码或自定义UICollectionViewFlowLayout

    
    class MainCollectionViewFlowLayout: UICollectionViewFlowLayout {
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
            let attr = super.layoutAttributesForElements(in: rect)
            var attributes = [UICollectionViewLayoutAttributes]()
            for itemAttributes in attr! {
                let itemAttributesCopy = itemAttributes.copy() as! UICollectionViewLayoutAttributes
                // manipulate itemAttributesCopy
                attributes.append(itemAttributesCopy)
            }
    
            if attributes.count == 1 {
    
                if let currentAttribute = attributes.first {
                    currentAttribute.frame = CGRect(x: self.sectionInset.left, y: currentAttribute.frame.origin.y, width: currentAttribute.frame.size.width, height: currentAttribute.frame.size.height)
                }
            } else {
                var sectionHeight: CGFloat = 0
    
                attributes.forEach { layoutAttribute in
                    guard layoutAttribute.representedElementCategory == .supplementaryView else {
                        return
                    }
    
                    if layoutAttribute.representedElementKind == UICollectionView.elementKindSectionHeader {
                        sectionHeight = layoutAttribute.frame.size.height
                    }
                }
    
                attributes.forEach { layoutAttribute in
                    guard layoutAttribute.representedElementCategory == .cell else {
                        return
                    }
    
                    if layoutAttribute.frame.origin.x == 0 {
                        sectionHeight = max(layoutAttribute.frame.minY, sectionHeight)
                    }
    
                    layoutAttribute.frame = CGRect(origin: CGPoint(x: layoutAttribute.frame.origin.x, y: sectionHeight), size: layoutAttribute.frame.size)
    
                }
            }
            return attributes
        }
    }
    
    

    注意:您需要先复制数组中的属性才能使用。否则 xcode 将在控制台中大喊 Logging only once for UICollectionViewFlowLayout cache mismatched frame

    如果有任何新的/完美的解决方案,请告诉我。

    干杯!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      • 2015-02-26
      • 2020-06-26
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多