【问题标题】:Swift 3: How to center horizontally the last row of cells in a UICollectionView with only one section?Swift 3:如何将 UICollectionView 中的最后一行单元格水平居中,只有一个部分?
【发布时间】:2016-12-11 21:10:03
【问题描述】:
【问题讨论】:
标签:
ios
uicollectionview
swift3
uicollectionviewcell
【解决方案1】:
听起来您需要流布局提供的所有内容,并进行一些自定义。子类化流布局和覆盖layoutAttributesForElements 应该可以完成这项工作:
一个快速而肮脏的实现基本上会要求 FlowLayout 为给定的矩形进行布局,然后找出最后一行出现的项目。如果少于 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
【解决方案2】:
简短的回答是:你不能,使用 Apple 提供的 UICollectionViewFlowLayout
更长的答案是:
您将不得不创建一个客户 UICollectionViewLayout 子类并自己放置元素。首先通过this tutorial。然后,您应该更好地了解内部工作原理,以便能够创建自己的自定义布局。
【解决方案3】:
只需在最后添加一个空单元格,即全角,之前的单元格将居中
【解决方案4】:
强文本您可以在您的 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
}
}