如何使水平自定义UICollectionView单元居中?

时间:2017-12-27 21:59:49

标签: ios swift uicollectionview autolayout

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

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

|[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] |

对于https://hub.docker.com/_/php/固定宽度的单元格,我找到了一个很好的答案,但不适用于自我大小的单元格。

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

1 个答案:

答案 0 :(得分:2)

真的很烦人,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. 计算margincontentWidth的宽度之间的(左+右)collectionView
  3. 必要时应用页边距*,这导致内容的输入

*负页边距表示内容大于collectionView,因此属性应保持不变=>可滚动并按预期对齐。