尽管宽度相等,但集合视图网格最后一行的显示方式不同 - swift iOS
Posted
技术标签:
【中文标题】尽管宽度相等,但集合视图网格最后一行的显示方式不同 - swift iOS【英文标题】:Collection view grid last row appears differently despite equal widths - swift iOS 【发布时间】:2019-05-08 07:45:53 【问题描述】:我有一个固定的集合视图单元格 (UICollectionView) 网格,但底行中的单元格在屏幕上总是以稍小的宽度出现。在 collectionViewLayout: UICollectionViewLayout sizeForItemAt 中使用的框架大小(或边界)和计算出的宽度对于所有行都是相同的。
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
let settings = currentContents[indexPath.item]
let height = CGFloat(30)
// https://***.com/questions/54915227/uicollectionview-remove-space-between-cells-with-7-items-per-row
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)
我想让底行与其他行对齐,但无法想象在布局委托方法(或如何修复)中返回值后改变宽度的情况。
【问题讨论】:
能否与我们分享示例演示代码 @iMHiteshSurani - 你指的是哪个演示代码?我有设置单元格宽度的完整 collectionViewLayout 方法。如果我在索引路径中删除除了 cellforitem 中的边框之外的所有内容,问题仍然存在 - 尽管它看起来不那么明显。 如果我删除了 settings.portion 的值——这样行中的所有单元格的宽度都相等——那么问题就消失了。也许有更好的方法来为每列单元格分配总行的比例?目前,所有 setting.portion 值的总和简单地等于列数。第一列部分:CGFloat(1.4),所有其他部分:CGFloat(0.9) 我创建并上传了一个项目来演示问题:github.com/DrWhen/Last-row-in-grid-error 【参考方案1】: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()
【讨论】:
谢谢 - 这很有意义,并且以非常简单的方式非常接近解决方案。仅...在 GitHub 项目中,如果您进行修复,请转到违规屏幕(文章和形容词)并选择选择器中的最小值(带有不定冠词的形容词('a')),然后间距问题是还在吗?!? 我更改了你的sizeForItemAt
方法并使用了let width = availableWidth / CGFloat(collectionContents.cellsPerRow5); return CGSize(width: width, height: 30).xx_rounded()
我不知道-1
和settings.portion
应该做什么。
我使用 settings.portions 以便某些列比其他列宽。对于行中的 5 个单元格 - 第一列的 .portions 为 1.4,其他 4 列的 .portions 为 0.9。我需要能够做到这一点。 “-1”也是一种处理剩余的方法。
如果你删除-1
?
在某些设备(例如 X)上,如果没有 -1,总宽度大于行宽,它会溢出到下一行并破坏网格。在 Git Hub 上,DeutschGramma.zip 显示了这一点。用你的方法更新这个文件,用今天的日期文件 - 如果你导航到“文章和形容词”并选择选择器中的最小值(“带有不定冠词的形容词('a')”),就会出现问题。网格的底行。【参考方案2】:
只需替换
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
【讨论】:
感谢您的浏览。尽管此解决方案确实在某些方向上解决了某些设备上的问题,但并非在所有情况下都有效。我将具有上述更改的整个项目放到同一个 GitHub 文件夹中以供下载。运行时 - 转到“文章和形容词结尾”查看网格表。如果您在 iPhone 8 上纵向运行,网格会完全中断,或者在 iPad Pro 上,底行再次与其他行不同。此外,如果您使用选择器在表格中设置值,选择器值“带有间接冠词的形容词”也会弄乱最后一行。【参考方案3】:我发现的最佳方法是在计算初始列宽后捕获剩余空间(减 1 以避免四舍五入),然后将剩余空间用于其他列。
对于两列示例:
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)
【讨论】:
以上是关于尽管宽度相等,但集合视图网格最后一行的显示方式不同 - swift iOS的主要内容,如果未能解决你的问题,请参考以下文章