UICollectionViewCell 中的动态高度 noScrollable UICollectionView

Posted

技术标签:

【中文标题】UICollectionViewCell 中的动态高度 noScrollable UICollectionView【英文标题】:Dynamic height noScrolable UICollectionView in UICollectionViewCell 【发布时间】:2016-12-07 09:03:02 【问题描述】:

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

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

这就是我想要的

让我们调用: 主集合视图:ParentCollectionView CollectionView内部:ChildCollectionView

我想获取 ChildCollectionView 的高度,以便我可以在 side 中设置 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 开发新手。 任何帮助将不胜感激:)

【问题讨论】:

由于您的集合视图的内容不可滚动,您可能需要重新考虑另一个集合视图中的集合视图。如果你真的必须做类似的事情,你实际上可以在你的委托方法中检查 collectionView == ParentCollectionView 以确定你当前正在与哪个交互。 在计算 ChildCollectionView 的大小方面,您需要详细说明如何计算它,然后我才能帮助您。但通常你应该能够设置约束来设置你的内容是你的 ChildCollectionView 在这种情况下是相对于它所在的单元格 @BenOng ChildCollectionView 在 ParentCollectionViewCell 内部初始化,并且其 dataSource 和 delegate 为 self .....我使用 collectionView.intrinsicContentSize.height 计算它 @BenOng - 并且设置了数据......我必须通过在 ParentCollectionView sizeForItemAt 中计算的这个值,以便单元格具有正确的高度,包括 ChildCollectionView 在这种情况下,您可以为您的 ChildCollectionView 创建一个自定义委托方法来更新其单元格大小的 ParentCollectionView 【参考方案1】:

这解决了我的问题

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)


【讨论】:

【参考方案2】:

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

我的想法是只添加每个标签的宽度(+ 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

这将导致以下结果:

【讨论】:

以上是关于UICollectionViewCell 中的动态高度 noScrollable UICollectionView的主要内容,如果未能解决你的问题,请参考以下文章

为啥向 UICollectionViewCell 中的按钮添加操作效果不佳?

嵌入在 UICollectionViewCell 中的自定尺寸 UITableView

动态设置 UICollectionViewCell 的大小

动态缩小 UICollectionViewCell 的高度

动态调整 UICollectionViewCell 的大小

使用图像上传 Swift 动态调整 UICollectionViewCell 的大小