Ios UICollectionView内部UITableViewCell如何根据屏幕大小调整tableview单元格高度

Ios UICollectionView内部UITableViewCell如何根据屏幕大小调整tableview单元格高度,ios,swift,uitableview,uicollectionview,Ios,Swift,Uitableview,Uicollectionview,我有下面的布局 UITableView UITableViewCell(类别:CategoryCell) 标签 钮扣 UICollectionView UICollectionViewCell(类:ItemCell) UIImageView UILabel 我试图使UICollectionView始终显示3个项目,无论屏幕大小。我能够根据屏幕宽度显示项目,并能够设置高度。但是,表视图的高度不会从内部CategoryCell更改。代码如下: // CategoryCell.sw

我有下面的布局

  • 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)

您可以实现
UITableViewDelegate
heightForRowAt
并基于变量返回值。您可以在执行
UICollectionView
itemHeight
计算的任何位置设置变量。因此,完成计算后,应该能够重新加载表视图数据,并且布局应该使用新的
itemHeight
值进行更新


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

您需要为每个单元格提供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 
}

试试这个,希望它能帮助你。

谢谢你@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)
会导致访问错误。

提供集合视图的约束,并在tableviewcell页面中设置collectionviewcell出口,以及在同一tableviewcell页面中设置collectionviewheight约束出口。 如tableviewcell页面中所示:

class HomeServiceTableCell:UITableViewCell{
@IBOutlet弱var dealsCollectionView:UICollectionView!
@IBOutlet弱var dealsCollectionHeight:NSLayoutConstraint!
@IBOutlet弱var dealsImage:UIImageView!
//类似于主页面中的cellforRowAt indexPath函数
func tableView(tableView:UITableView,cellForRowAt indexath:indexPath)->UITableViewCell{
将cell=homeServiceTable.dequeueReusableCell(标识符为:“homeServiceTableCell6”)设为!homeServiceTableCell6
cell.dealsImage.image=UIImage(名为:“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
返回单元
}
func tableView(tableView:UITableView,heightForRowAt indexath:indexPath)->CGFloat{
返回UITableViewAutomaticDimension
}
//最后在VIEWWILLEXPEND函数中添加这一行
覆盖函数视图将出现(uo动画:Bool){
self.homeServiceTable.layoutSubviews()
}
}

动态高度不适合我。“固定高度”确实显示具有我指定的高度的单元格。但是,tableViewCell不会更新tableView本身。请将tableView的数据源和委托代码发布到此处,我添加了数据源代码。我的委托代码只包含您上面提供的内容。此外,我认为我找到了一个不同的解决方案。您可以从tableview中获取cell,如下所示:let cell=tableview.cellForRow(at:indexPath)as!yourCellClass注意,如果单元格不可见或索引路径超出范围,它将返回nil。我将继续获取EXC\u BAD\u访问。您想在哪里访问它?如果尚未创建单元格,则无法访问它。可以根据数组中的数据计算大小。我的意思是你可以使用索引路径来计算大小。是的,但是保护变量也会给EXC\u BAD\u访问权限。我将有两个原型单元,所以我希望每个单元的类都能计算大小和
heightForRowAt
刚才调用函数来计算单元