尽管宽度相等,但集合视图网格的最后一行显示不同 - swift iOS

Collection view grid last row appears differently despite equal widths - swift iOS

我有一个固定的集合视图单元格 (UICollectionView) 网格,但底部行中的单元格在屏幕上总是显示为略小的宽度。 collectionViewLayout: UICollectionViewLayout sizeForItemAt 中使用的框架大小(或边界)和计算宽度对于所有行都是相同的。

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    let settings = currentContents[indexPath.item]
    let height = CGFloat(30)

    // 
    var cellWidth = CGFloat()
    let availableWidth = collectionView.bounds.size.width
    print("available width", availableWidth)
    let minimumWidth = floor(availableWidth / collectionContents.cellsPerRow5)
    print("minmum width", minimumWidth)
    cellWidth = minimumWidth * settings.portion - 1
    print("cell width", cellWidth)

    return CGSize(width: cellWidth, height: height)
}

我想让底行与其他行对齐,但无法想象在布局委托方法中返回值后改变宽度的情况(或如何修复) .

替换

即可
cellWidth = (minimumWidth * settings.portion) - 0.5

cellWidth = (minimumWidth * settings.portion)

指定 minimumInteritemSpacingForSectionAt 为 0.5 而不是 0

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0.5
}

CVTVCell.swift

只需在将数据集放入 currentContents 后,在 awakeFromNib 方法中重新加载 UICollectionView。请参考下面的示例代码。

override func awakeFromNib(){
    super.awakeFromNib()
    currentContents = collectionContents.allEndings[0]
    self.cView.reloadData()
}

Download code from here

UIKit 不喜欢超过 2 位小数的值,将它们四舍五入或者它会为你做。

此处,UICollectionViewFlowLayout 舍入您的单元格大小并开始使用至少等于您指定的 minimumInteritemSpacing 的 "interitemspacing" 填充行。在最后一行,它恰好使用了 minimumInteritemSpacing 值,并没有填满整行。

使用更好的四舍五入值修复它,给人一种一切都完美对齐的错觉。

我通常使用这些扩展名:

extension CGFloat {
    func xx_rounded(_ rule: FloatingPointRoundingRule = .down, toDecimals decimals: Int = 2) -> CGFloat {
        let multiplier = CGFloat(pow(10.0, CGFloat(decimals)))
        return (self * multiplier).rounded(.down) / multiplier
    }
}

extension CGSize {
    func xx_rounded(rule: FloatingPointRoundingRule = .down, toDecimals: Int = 2) -> CGSize {
        return CGSize(
            width: width.xx_rounded(rule, toDecimals: toDecimals),
            height: height.xx_rounded(rule, toDecimals: toDecimals)
        )
    }
}

变化:

return CGSize(width: cellWidth, height: height)

return CGSize(width: cellWidth, height: height).xx_rounded()

我发现的最佳方法是在计算初始列宽后捕获剩余的 space(减 1 以避免向上舍入),然后将剩余的 space 用于其他列。

对于两列示例:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    if indexPath.item == 0 || indexPath.item == 1
    { rowHeight = 40 }
    else { rowHeight = 30 }
    var cellWidth = CGFloat()
    let minimumWidth = floor(availableWidth / numberOfColumns)
    var columnPortion = CGFloat()
    let columnNumber = indexPath.item % Int(numberOfColumns)
    switch columnNumber
    {
    case 0:
        columnPortion = columnPortion1
        cellWidth = minimumWidth * columnPortion - 10
        remainder = availableWidth - cellWidth - 1
    case 1:
        columnPortion = columnPortionFinal
        cellWidth = remainder
    default:
        break
    }
    return CGSize(width: cellWidth, height: rowHeight)
}