仅通过autolayout确定UICollectionView单元格高度

时间:2017-12-29 02:19:53

标签: ios uicollectionview uicollectionviewcell uicollectionviewlayout

我需要一个在网格中显示单元格的集合视图。所以标准的流程布局对我来说很好。但是,我想知道每行要显示多少个单元格,而单元格高度应该由我放在单元格上的自动布局约束来确定。这是我的单元格布局:

enter image description here

这很简单 - 图像视图和下面的两个标签。现在图像视图有一个宽高比约束(1:1),这意味着每当单元格已知宽度时,自动布局规则就会自动知道高度(有垂直约束通过:开发的Celltop-图像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以使整个机制开始工作。

结果很奇怪 - 看起来集合视图没有考虑到我返回的宽度,主要取决于标签长度:

enter image description here

我已经看到了一些其他的答案,人们建议手动计算单元格的宽度,比如告诉"自己布局,然后测量自己,然后给我你这个宽度的大小",即使它会仍然在引擎盖下运行autolayout规则,我想知道是否有一种方法可以做到这一点,而无需手动弄乱大小。

2 个答案:

答案 0 :(得分:0)

您可以在故事板的尺寸检查器中轻松找到collectionView单元格的高度,如下所示:

enter image description here

现在,只需从此处获取此高度,然后将其传递给重写的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**)
}

您将获得所需的输出。

答案 1 :(得分:0)

我最终实现了将所有内容移至自动布局的技巧。我完全删除了委托方法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
}

这与启用自动布局单元大小调整一起将正确布置单元格。