【问题标题】:How to center horizontally self-sizing UICollectionView Cells?如何水平居中自定大小的 UICollectionView 单元格?
【发布时间】:2018-06-08 12:12:51
【问题描述】:

我有一个collectionView,方向设置为Horizo​​ntal,每个单元格只包含一个UIlabel,它使用自动布局来确定单元格的宽度。

例如,有三个单元格,这是默认行为。

|[x] [xxx] [xxxxxxxxx] |

但如果所有单元格的总宽度不超过屏幕宽度,则要求将这三个单元格居中对齐。

第一个单元格的左插图应该是

leftInset = (screen width - (first cell width + second cell width + third cell width + total spaces between the three cells) /) 2

结果是

| [x] [xxx] [xxxxxxxxx] |

我从How to center horizontally UICollectionView Cells? 找到了固定宽度的单元格的一个很好的答案,但不适用于自身大小的单元格。

如果您能提供帮助,我们将不胜感激。

【问题讨论】:

  • 我认为您需要考虑创建自己的 UICollectionViewLayout 来根据需要定位单元格。本教程展示了如何做到这一点的基础知识link
  • 我遇到了同样的问题。

标签: ios swift uicollectionview autolayout


【解决方案1】:

真的很烦人,Apple 没有为这些东西提供现成的布局......

最后我想出了以下流程布局:

class HorizontallyCenteredCollectionViewFlowLayout: UICollectionViewFlowLayout {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.scrollDirection = .horizontal
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }
        guard let collectionView = self.collectionView,
            let rightmostEdge = attributes.map({ $0.frame.maxX }).max() else { return attributes }

        let contentWidth = rightmostEdge + self.sectionInset.right
        let margin = (collectionView.bounds.width - contentWidth) / 2

        if margin > 0 {
            let newAttributes: [UICollectionViewLayoutAttributes]? = attributes
                .compactMap {
                    let newAttribute = $0.copy() as? UICollectionViewLayoutAttributes
                    newAttribute?.frame.origin.x += margin
                    return newAttribute
            }

            return newAttributes
        }

        return attributes
    }
}

这基本上包括以下步骤:

  1. 计算contentWidth
  2. 计算contentWidthcollectionViews宽度之间的(左+右)margin
  3. 必要时应用边距*,这会导致输入内容

* 负边距意味着内容大于collectionView,因此属性应保持不变 => 可滚动且左对齐,如预期的那样。

【讨论】:

  • 这对我来说效果很好,但似乎假设last.frame.maxX 是最右边的边缘,这并不总是正确的。我认为使用attributes.map { $0.frame.maxX }.max()会更健壮?
  • @Tom Thx 对于这个概念,刚刚相应地更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2023-04-04
  • 2016-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 2015-04-07
  • 2012-12-27
  • 1970-01-01
相关资源
最近更新 更多