【问题标题】:UICollectionView inside UITableViewCell how to adjust tableview cell height based on screen sizeUITableViewCell内的UICollectionView如何根据屏幕大小调整tableview单元格高度
【发布时间】:2017-03-25 00:45:25
【问题描述】:

我有以下布局

  • UITableView
    • UITableViewCell(类:CategoryCell)
      • 标签
      • 按钮
      • UICollectionView
        • UICollectionViewCell(类:ItemCell)
          • UIImageView
          • UILabel

我正在尝试让 UICollectionView 始终显示 3 个项目,无论屏幕大小如何。我能够根据屏幕宽度显示要显示的项目,并且能够设置高度。但是,表格视图的高度不会从 CategoryCell 内部改变。代码如下:

// CategoryCell.swift

func awakeFromNib() {
    super.awakeFromNib()

    // Calculate width and height based on screen width
    let screenWidth = UIScreen.main.bounds.width
    let itemWidth = screenWidth / 3.0
    let itemHeight = itemWidth / 0.75 // 3:4 aspect ratio

    // Change height of table view cell
    self.bounds.size.height = self.bounds.size.height - collectionView.bounds.size.height + itemHeight
    // This is the line does nothing
    // It should remove collectionView height from tableView (height of collectionView is set through autolayout) then add he new height to it.

    // Set collection view height to equal to item height
    collectionView.bounds.size.height = itemHeight

    // set item height
    let layout = collectionViewProducts.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: itemWidth, height: itemHeight - 1.0)
    // -1.0 because item/cell height needs to be SMALLER than collection view height
}

如何从单元格类本身更改表格视图单元格的高度?我唯一的猜测是我不应该在 awakeFromNib 中执行这些操作,但我无法找到另一个函数来调用这些操作。

编辑:我使用的是 RxSwift,所以我的数据源代码如下:

let observable = Observable.just(data)
observable.bindTo(tableView.rx.items(cellIdentifier: "CategoryCell", cellType: CategoryCell.self)) { (row, element, cell) in
    cell.setCategory(category: element)
}.disposed(by: disposeBag)

tableView.rx.setDelegate(self).disposed(by: disposeBag)

【问题讨论】:

    标签: ios swift uitableview uicollectionview


    【解决方案1】:

    您可以实现UITableViewDelegateheightForRowAt 并根据变量返回一个值。无论您在哪里进行UICollectionView itemHeight 计算,都可以设置变量。因此,当您完成计算后,您应该能够重新加载表格视图数据,并且应该使用新的 itemHeight 值更新布局。

    我还没有测试过代码,但上面应该可以工作。如果您遇到任何问题,或者我以某种方式误解了您的要求,请告诉我。

    【讨论】:

      【解决方案2】:

      为collection view提供约束,在tableviewcell页面中设置collectionviewcell出口,在同一个tableviewcell页面中设置collectionviewheight约束出口。 在 tableviewcell 页面中像这样:

      class HomeServiceTableCell: UITableViewCell {
      
        @IBOutlet weak var dealsCollectionView: UICollectionView!
        @IBOutlet weak var dealsCollectionHeight: NSLayoutConstraint!
        @IBOutlet weak var dealsImage: UIImageView!
      
        // like this in the main page cellforRowAt indexPath function
      
        func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cell = homeServiceTable.dequeueReusableCell ( withIdentifier:  "homeServiceTableCell6" ) as! homeServiceTableCell6
          cell.dealsImage.image = UIImage(named: "deals.png")
          cell.dealsCollectionView.tag = indexPath.row
          cell.dealsCollectionView.delegate = self
          cell.dealsCollectionView.dataSource = self
          cell.dealsCollectionView.reloadData()
          cell.dealsCollectionHeight.constant = cell.dealsCollectionView.collectionViewLayout.collectionViewContentSize.height
      
          return cell
        }
      
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat  {
          return UITableViewAutomaticDimension
        }
      
        // lastly add this line in viewWillAppear function
      
        override func viewWillAppear(_ animated: Bool) {
          self.homeServiceTable.layoutSubviews()
        }
      }
      

      【讨论】:

        【解决方案3】:

        您需要为每个单元格提供 tableview 的单元格高度,并在此基础上计算您的 collectionview 单元格的高度。对于 tableview 的单元格的动态高度,您需要实现这些方法。

        func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
            return UITableViewAutomaticDimension
        }
        
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return UITableViewAutomaticDimension
        }
        

        或者如果您需要固定高度,则只需使用这些方法并根据您的计算提供您的单元格高度。

        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return fixedSize //e.g 100 
        }
        

        试试这个希望对你有帮助。

        【讨论】:

        • 动态高度对我不起作用。固定高度确实显示了一个具有我指定高度的单元格。但是,tableViewCell 不会更新 tableView 本身。
        • 你能把你的tableview的数据源和委托代码贴在这里
        • 我添加了数据源代码。我的委托代码只有您在上面提供的代码。
        • 另外,我想我找到了不同的解决方案。
        【解决方案4】:

        谢谢@Prince 和@Fahim。您的回答让我想到了将行高逻辑移动到 tableView 委托。因为,我根据屏幕宽度和纵横比计算高度。我只是将相同的逻辑移至 tableView 高度:

        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            let screenWidth = UIScreen.main.bounds.size.width
        
            // 3 items + 10px gap between cells
            let itemWidth = (screenWidth / 3.0) - 20
        
            // 3:4 aspect ratio + other elements
            let itemHeight = (itemWidth) / 0.75 + 110
        
            return itemHeight
        }
        

        现在这个解决方案对我来说正常工作,我想改变它,以便它考虑到单元格本身。

        我知道在答案中问一个问题很奇怪,但它与这个线程有关,所以我认为最好在这里问。如何从 indexPath 获取单元格对象?使用 tableView.cellForRow(at: indexPath) 让我无法访问。

        【讨论】:

        • 你可以像这样从 tableview 获取单元格 let cell = tableView.cellForRow(at: indexPath) as! yourCellClass 请注意,如果单元格不可见或索引路径超出范围,它将返回 nil
        • 我不断收到 EXC_BAD_ACCES。
        • 你想在哪里访问它?如果尚未创建单元格,则无法访问它。
        • 您可以根据数组中的数据计算大小。我的意思是你可以使用索引路径来计算大小。
        • 是的,但是保护变量也会给出 EXC_BAD_ACCESS。我将有两个原型单元格,所以我希望每个单元格的类来计算大小,heightForRowAt 只是调用函数来计算单元格
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-26
        • 2021-09-28
        • 1970-01-01
        • 2016-05-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多