我需要一个集合视图,它在网格中显示单元格。所以标准的流程布局对我来说很好。但是,我想知道每行要显示多少个单元格,而单元格高度应该由我放在单元格上的自动布局约束来确定。这是我的单元格布局:
它非常简单 - 图像视图和它下面的两个标签。现在,图像视图具有宽高比约束(1:1),这意味着无论何时单元格的宽度已知,高度应自动为自动布局规则所知(存在垂直约束:celltop-image-label1-label2 -cellbottom)。
现在,因为我不知道任何其他好方法告诉集合视图每行显示2个项目,我已经覆盖了UICollectionViewDelegateFlowLayout
方法:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let availableWidth = collectionView.frame.width - padding
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
正如你所看到的,因为我不知道项目高度我返回与宽度相同的东西,希望自动布局稍后将修复它。我还设置了estimatedItemSize
以便整个机制开始工作。
结果很奇怪 - 似乎集合视图没有事件考虑到我返回的宽度,主要取决于标签长度:
我已经看到了一些其他的答案,人们建议手动计算单元格的宽度,比如说“自己布局,然后测量自己,然后给我这个宽度的大小”,即使它仍然会在引擎盖下运行自动布局规则,我想知道是否有办法做到这一点,而无需手动搞乱大小。
您可以在故事板大小检查器中轻松找到集合的高度查看单元格,如下所示:
现在,从这里获取此高度,并将其传递给重写的UICollectionViewDelegateFlowLayout
方法:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let availableWidth = collectionView.frame.width - padding
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: **114**)
}
您将获得所需的输出。
我最终实现了一个把一切都移到自动布局的技巧。我完全删除了委托方法func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
并在界面构建器中为我的单元格内容添加了宽度约束(将初始值设置为某些东西,这并不重要)。然后,我在自定义单元格类中为该约束创建了一个出口:
class MyCell: UICollectionViewCell {
@IBOutlet weak var cellContentWidth: NSLayoutConstraint!
func updateCellWidth(width: CGFloat) {
cellContentWidth.constant = width
}
}
稍后,当创建单元格时,我会根据每行所需的单元格数量将宽度约束更新为预先计算的值:
private var cellWidth: CGFloat {
let paddingSpace = itemSpacing * (itemsPerRow - 1) + sectionInsets.left + sectionInsets.right
let availableWidth = collectionView.frame.width - paddingSpace
return availableWidth / itemsPerRow
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
...
cell.updateCellWidth(width: cellWidth)
return cell
}
并且,与启用自动布局单元大小调整一起,将正确布置单元格。