UICollectionViewCell 中的动态高度 noScrolable UICollectionView

Dynamic height noScrolable UICollectionView in UICollectionViewCell

我想在UICollectionViewCell中添加一个dynamic heightnonScrollableUICollectionView。 (如 Ash Furrow 所解释的,在 UICollectionViewCell 中添加一个静态高度的 UICollectionView 很容易)

在网上搜索了几个小时后,我仍然不明白。

这就是我想要的

让我们打电话: 主 CollectionView:ParentCollectionView
CollectionView 内部:ChildCollectionView

我想获取 ChildCollectionView 的高度,以便我可以在侧面设置 ParentCollectionView 的单元格大小:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let text = "I'm trying to get a label in a cell.."
        let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
        let estimatedFrameForEventText = (text as NSString).boundingRect(with: CGSize.init(width: view.frame.width - 30, height: 1000), options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 12)], context: nil)
        return CGSize.init(width: view.frame.width - 10, height: 320 + estimatedFrameForEventText.height + 60)
}

还想用这个更改 ChildCollectionView 的高度常量:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: eventCellId, for: indexPath) as! EventCell
        cell.eventText.text = "I'm trying to get a label in a cell.."

        // height constraint of ChildCollectionView in ParentCell
        cell.collectionViewHeightConstraint.constant = cell.collectionView.intrinsicContentSize.height
        return cell
}

有意禁用 ChildCollectionView 的滚动以一起显示 ChildCollectionViewCells。

这就是我卡住的地方

我不会预先计算 ChildCollectionView 以将它们传递给 ParentCollectionView 委托

CollectionView 都使用 UICollectionViewFlowLayout

我是 iOS 开发新手。 任何帮助将不胜感激:)

这解决了我的问题

ParentCollectionViewController

var height: CGFloat!

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: eventCellId, for: indexPath) as! EventCell

    cell.collectionViewHeightConstraint.constant = height!
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    var sizeOfChildCell: CGRect!
    var widthOfCells: CGFloat! = 0.0
    let cellPadding = 10
    let widthOfChildCollectionview = view.frame.width - 120
    for tag in tags {
        sizeOfChildCell = ("#\(tag)" as NSString).boundingRect(with: CGSize.init(width: widthOfChildCollectionview, height: 1000), options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 12)], context: nil)
        widthOfCells = widthOfCells + sizeOfChildCell.width + cellPadding + 3.8
    }
    let numOfRows = ceil(widthOfCells / widthOfChildCollectionview)
    height = numOfRows  * 25
    height = height + numOfRows * 3.8
    return CGSize.init(width: view.frame.width - 10, height: 320  + height)
}

ParentCollectionViewCell

var childCollectionViewHeightConstraint: NSLayoutConstraint!

lazy var childCollectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.showsVerticalScrollIndicator = false
    cv.isScrollEnabled = false
    cv.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    cv.backgroundColor = .white
    cv.dataSource = self
    cv.delegate = self
    return cv
}()

 override init(frame: CGRect) {
    super.init(frame: frame)

    childCollectionViewHeightConstraint = NSLayoutConstraint(item: childCollectionView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 96)
    addConstraint(childCollectionViewHeightConstraint)

}

仅供以后搜索此主题。我将 IGListKit 与一个单元格一起使用,该单元格包含一个包含我的标签的 UICollectionView。我的问题是 IGListKit 没有很好地建立在 AutoLayout 原则上,因此为了防止 collectionview 单元格相互重叠,我必须在显示之前手动计算该部分的高度。

我的想法是只添加每个标签的宽度 (+ padding + minimumInterimSpace) 并确定下一个标签何时取代集合视图宽度。

func calculateDimensions() {
   //This is how IGListKit forwards the width, could be replaced with collectionView.containerSize.width
   let width = collectionContext!.containerSize.width

   var lineWidth:CGFloat = 0.0
   var lines = 0
   for tag in data.arrTags {
       //Calculate bounds by using boundingRect
       let size = TextSize.size(tag, font: Font.fontRegular(size: 13), height: 30)
       //16= 8 padding-left + 8 padding-right 
       //5 = minimumInterimSpace
       let itemWidth = 16 + size.width + 5 
       let tmpWidth = lineWidth + itemWidth
       if tmpWidth > width {
           lines += 1
           lineWidth = itemWidth
       }
       lineWidth += itemWidth
    }

    sectionHeight = CGFloat( lines * 30 + (lines * 5)) + 15 
}

当 IGListKit 设置当前部分的大小时调用此方法。所以我这样做了:

override func sizeForItem(at index: Int) -> CGSize {
    calculateDimensions()
    let size = CGSize(width: collectionContext!.containerSize.width, height: sectionHeight)
    return size
}

这将导致以下结果: