Swift 3:如何在UICollectionView中仅使用一个部分水平居中最后一行单元格?

时间:2016-12-11 21:10:03

标签: ios uicollectionview swift3 uicollectionviewcell

我只使用UICollectionView只有一个部分。这里有一些可视化:

[ x x x ]  
[ x x x ]  
[ x x   ] 

如果UICollectionView中的最后一行没有填充所有3个单元格,我希望将这些单元格置于中心位置:

[ x x x ]  
[ x x x ]  
[  x x  ] 

我试图从以下地方实施解决方案:

  1. How to center horizontally UICollectionView Cells?

  2. How to center align the cells of a UICollectionView?

  3. 然而,解决方案会移动所有单元格,并且如果最后一行不包含X个单元格,我只想移动最后一行,因为我只有一个单元格。

    我知道如何设置插图,但我不知道如何通过只有一个部分并尝试调整最后一行单元格的插入来实现此目的。

    我刚开始使用UICollectionView而不确定如何解决此问题?

4 个答案:

答案 0 :(得分:5)

听起来您需要流布局提供的所有内容以及一些自定义。子类化流程布局和覆盖layoutAttributesForElements应该完成这项工作:

快速而脏的实现基本上会要求FlowLayout为给定的rect做布局,然后找出最后一行中出现的项目。如果少于3个项目,则将它们均匀分开。

class LastRowCenteredLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard var elementAttributes = super.layoutAttributesForElements(in: rect) else { return nil }
        guard elementAttributes.count > 0 else { return elementAttributes }

        elementAttributes = elementAttributes.map { $0.copy() as! UICollectionViewLayoutAttributes }

        let minY = elementAttributes.last!.frame.minY
        let lastRowAttrs = elementAttributes.reversed().filter { $0.frame.minY == minY }

        guard lastRowAttrs.count < 3,
                let first = elementAttributes.first,
                let last = elementAttributes.last else {
            return elementAttributes
        }

        let horizontalPadding = rect.width - first.frame.minX - last.frame.maxX
        let horizontalShift = horizontalPadding / 2.0

        for attrs in lastRowAttrs {
            attrs.frame = attrs.frame.offsetBy(dx: horizontalShift, dy: 0)
        }

        return elementAttributes
    }
}

请注意,如果您计划动画插入/删除,则还应覆盖layoutAttributesForCellWithIndexPath:并确保其返回一致的结果。

Apple在FlowLayout上有一个guide,其中有一节专门用于子类化。

游乐场示例:

https://gist.github.com/AnuragMishra/0a694dfa9be1a5eab9fc7368b69812ad

答案 1 :(得分:0)

简短的回答是:你不能,使用Apple提供的UICollectionViewFlowLayout

答案越长越好: 您将不得不创建一个客户UICollectionViewLayout子类并自己放置该元素。首先浏览this tutorial。然后,您应该更好地了解内部工作,以便能够创建自己的自定义布局。

答案 2 :(得分:0)

强文本,您可以在collectionViewLayout函数中进行此简单计算。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    //return itemSize
    let spaceBetweenCell :CGFloat = 0
    let screenWidth = UIScreen.main.bounds.size.width - CGFloat(2 * spaceBetweenCell)
    let totalSpace = spaceBetweenCell * 1.0
    if indexPath.row == categories.count-1 {
      // check if last cell is odd
      if categories.count % 2  == 1 {
        return CGSize(width: screenWidth , height: (screenWidth-totalSpace)/4) // all Width and  same previous height
      }else {
        return itemSize
      }
    }else{
      return itemSize
    }
  }

答案 3 :(得分:0)

只需在末尾添加一个全角的空单元格,之前的单元格将居中