首次加载时 UICollectionViewCell 内容大小错误
UICollectionViewCell content wrong size on first load
我已将 UICollectionView
添加到我的 UIViewController
并为其制作了一个自定义单元格。
我使用 sizeForItemAtIndexPath
方法设置单元格的大小,并将每个单元格的高度和宽度设置为 UIScreen.mainScreen().bounds.width/2
。所以本质上,每个单元格都是屏幕宽度的一半,高度也是相同的长度。
然后我在单元格内有一个 UIImageView
,每个边缘都固定到单元格的相对边缘,以便图像视图填充单元格。我还有一个 UILabel
在单元格中垂直和水平居中。
然而,在第一次加载时,单元格大小正确,但左上角的小方块中的内容要小得多。 (如下图所示,我已将单元格的 contentView 背景颜色设置为绿色,将 imageView 背景颜色设置为红色)。
然后在向下滚动一点后(我假设一个可重复使用的单元格被出列)所有单元格都很好(并且在向上滚动后保持良好)。
是什么导致内容在首次加载时未被正确约束?
更新
我的一些代码 UIViewController
:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("PrevDrawCell", forIndexPath: indexPath) as? PrevDrawCell
if cell == nil {
cell = PrevDrawCell()
}
cell!.drawVC = self
cell!.imageShortCode = self.tempImageURLs[indexPath.row]
// Pull image (async) and set after download
cell!.setupImage()
cell!.contentView.backgroundColor = UIColor.greenColor()
cell!.coverView.backgroundColor = UIColor.redColor()
cell!.dateLabel.font = UIFont(name: "HelveticaNeue-Light", size: 26)
cell!.dateLabel.text = "\(self.tempImageURLs.count-indexPath.row)/9"
return cell!
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let size = UIScreen.mainScreen().bounds.width/2
return CGSize(width: size, height: size)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsZero
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
看起来它仍然保留 contentView 的 100x100px 基本尺寸,而单元格本身已经获得正确的尺寸。您可以强制布局重置,在 return 单元格之前添加以下行:
cell?.layoutIfNeeded()
我曾经遇到过类似的问题(即使自动布局正确,我的单元格内容也不适合单元格)。该错误是由于未调用引起的
super.layoutSubviews()
在单元格 class.
中的重写函数 layoutSubviews() 中
对于使用 Storyboard + AutoLayout 并选择在运行时激活哪些约束的用户:
当使用 dequeueReusableCell 时,在第一次加载时,单元格已创建但其视图尚未初始化,因此不会保存约束更改 - 无论您在 Storyboard 中设置什么都会被使用。我的解决方案是在加载视图后更新约束:
override func layoutSubviews() {
super.layoutSubviews()
adjustIconWidths()
}
感谢 vin047 的精彩提示。
在我们的案例中,我发现问题出在超级调用顺序问题上。
但是使用总体table视图(或集合视图)。不在单元格中。
作品:
class UnusualCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
}
非常不规律地失败,尤其是第一次出现时:
class UnusualCollectionView: UICollectionView {
override func layoutSubviews() {
contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
super.layoutSubviews()
}
这个问题导致了一些非常不稳定的行为。例如,第 12 个单元格(不是真的)总是垂直移动很长一段距离。始终是第 12 个单元格!谁知道?
vin047 在这里化险为夷,太棒了。
对我有用的是将 Collection 视图上的 Estimate Size
从自动更改为 None。
在我的例子中,我需要指定单元格的高度等于 collectionView 的高度。但是集合视图的高度取决于屏幕的大小。
所以里面 sizeForItemAt delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: currentScreenWidth, height: collectionView.frame.height)
}
为了完成这项工作,我需要从 viewDidLayoutSubviews 调用 reloadData 函数
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
mycollection.reloadData()
}
我有一个类似的问题,不完全相同,但可以帮助别人。
我没有在单元格中调用 super.prepareForReuse()
就覆盖了 prepareForReuse。因此,当我将 UICollectionViewCompositionalLayout 与 .estimated(100) 一起用于单元格高度时,我在设备旋转时出现了奇怪的行为:如果旋转而不滚动,则在视图出现之后,然后滚动 - 你将拥有估计高度 (100) 的单元格,而不是随着布局更新。
所以,尝试检查这部分:
override func prepareForReuse() {
super.prepareForReuse()
}
嘿伙计们,如果仍然有人因为自动调整单元格而无法设置内容大小,你可以将它添加到你的集合视图中,你可以获得内容大小
*此处滚动使视图获得正确的内容大小,因此使您的 CollectionView 可滚动或禁用它,在这两种情况下,您将在单元格中加载数据后获得内容大小
`XCollectionView.isScrollEnabled = true/false`
*然后从数据源重新加载数据
`XCollectionView.reloadData()`
*然后调用layoutneeded
`XCollectionView.layoutIfNedded()`
*然后你可以检查,内容大小将等于你的内容
`XCollectionView.collectionViewLayout.collectionViewContentSize.height`
*现在将集合视图的高度设置为内容高度,一切顺利
我已将 UICollectionView
添加到我的 UIViewController
并为其制作了一个自定义单元格。
我使用 sizeForItemAtIndexPath
方法设置单元格的大小,并将每个单元格的高度和宽度设置为 UIScreen.mainScreen().bounds.width/2
。所以本质上,每个单元格都是屏幕宽度的一半,高度也是相同的长度。
然后我在单元格内有一个 UIImageView
,每个边缘都固定到单元格的相对边缘,以便图像视图填充单元格。我还有一个 UILabel
在单元格中垂直和水平居中。
然而,在第一次加载时,单元格大小正确,但左上角的小方块中的内容要小得多。 (如下图所示,我已将单元格的 contentView 背景颜色设置为绿色,将 imageView 背景颜色设置为红色)。
然后在向下滚动一点后(我假设一个可重复使用的单元格被出列)所有单元格都很好(并且在向上滚动后保持良好)。
是什么导致内容在首次加载时未被正确约束?
更新
我的一些代码 UIViewController
:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("PrevDrawCell", forIndexPath: indexPath) as? PrevDrawCell
if cell == nil {
cell = PrevDrawCell()
}
cell!.drawVC = self
cell!.imageShortCode = self.tempImageURLs[indexPath.row]
// Pull image (async) and set after download
cell!.setupImage()
cell!.contentView.backgroundColor = UIColor.greenColor()
cell!.coverView.backgroundColor = UIColor.redColor()
cell!.dateLabel.font = UIFont(name: "HelveticaNeue-Light", size: 26)
cell!.dateLabel.text = "\(self.tempImageURLs.count-indexPath.row)/9"
return cell!
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let size = UIScreen.mainScreen().bounds.width/2
return CGSize(width: size, height: size)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsZero
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
看起来它仍然保留 contentView 的 100x100px 基本尺寸,而单元格本身已经获得正确的尺寸。您可以强制布局重置,在 return 单元格之前添加以下行:
cell?.layoutIfNeeded()
我曾经遇到过类似的问题(即使自动布局正确,我的单元格内容也不适合单元格)。该错误是由于未调用引起的
super.layoutSubviews()
在单元格 class.
对于使用 Storyboard + AutoLayout 并选择在运行时激活哪些约束的用户:
当使用 dequeueReusableCell 时,在第一次加载时,单元格已创建但其视图尚未初始化,因此不会保存约束更改 - 无论您在 Storyboard 中设置什么都会被使用。我的解决方案是在加载视图后更新约束:
override func layoutSubviews() {
super.layoutSubviews()
adjustIconWidths()
}
感谢 vin047 的精彩提示。
在我们的案例中,我发现问题出在超级调用顺序问题上。
但是使用总体table视图(或集合视图)。不在单元格中。
作品:
class UnusualCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
}
非常不规律地失败,尤其是第一次出现时:
class UnusualCollectionView: UICollectionView {
override func layoutSubviews() {
contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
super.layoutSubviews()
}
这个问题导致了一些非常不稳定的行为。例如,第 12 个单元格(不是真的)总是垂直移动很长一段距离。始终是第 12 个单元格!谁知道?
vin047 在这里化险为夷,太棒了。
对我有用的是将 Collection 视图上的 Estimate Size
从自动更改为 None。
在我的例子中,我需要指定单元格的高度等于 collectionView 的高度。但是集合视图的高度取决于屏幕的大小。 所以里面 sizeForItemAt delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: currentScreenWidth, height: collectionView.frame.height)
}
为了完成这项工作,我需要从 viewDidLayoutSubviews 调用 reloadData 函数
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
mycollection.reloadData()
}
我有一个类似的问题,不完全相同,但可以帮助别人。
我没有在单元格中调用 super.prepareForReuse()
就覆盖了 prepareForReuse。因此,当我将 UICollectionViewCompositionalLayout 与 .estimated(100) 一起用于单元格高度时,我在设备旋转时出现了奇怪的行为:如果旋转而不滚动,则在视图出现之后,然后滚动 - 你将拥有估计高度 (100) 的单元格,而不是随着布局更新。
所以,尝试检查这部分:
override func prepareForReuse() {
super.prepareForReuse()
}
嘿伙计们,如果仍然有人因为自动调整单元格而无法设置内容大小,你可以将它添加到你的集合视图中,你可以获得内容大小
*此处滚动使视图获得正确的内容大小,因此使您的 CollectionView 可滚动或禁用它,在这两种情况下,您将在单元格中加载数据后获得内容大小
`XCollectionView.isScrollEnabled = true/false`
*然后从数据源重新加载数据
`XCollectionView.reloadData()`
*然后调用layoutneeded
`XCollectionView.layoutIfNedded()`
*然后你可以检查,内容大小将等于你的内容
`XCollectionView.collectionViewLayout.collectionViewContentSize.height`
*现在将集合视图的高度设置为内容高度,一切顺利