【问题标题】:Dynamic Height Issue for UITableView Cells (Swift)UITableView 单元格的动态高度问题(Swift)
【发布时间】:2015-08-10 06:16:28
【问题描述】:

可变长度的文本数据被注入到 tableview 单元格标签中。为了使每个单元格高度的大小合适,我在viewDidLoad() 中实现了:

self.tableView.estimatedRowHeight = 88.0
self.tableView.rowHeight = UITableViewAutomaticDimension

这估计高度为 88.0 像素,如果更大,则应自动调整高度。它非常适用于尚未滚动到的单元格(因为滚动单元格时调用UITableViewAutomaticDimention),但不适用于最初呈现在屏幕上的单元格在用数据加载表格时。

我已尝试重新加载数据(如许多其他资源中所建议的那样):

self.tableView.reloadData()

viewDidAppear()viewWillAppear() 中都没有帮助。我迷路了.. 有人知道如何渲染最初加载到屏幕上的单元格的动态高度吗?

【问题讨论】:

  • 您对单元格设置的高度限制是否正确,我在使用 Xcode 6.3 版本时没有看到任何问题。甚至在 github 上也有一个示例项目。 github.com/darren102/DTFAutomaticCellHeight
  • 我通过过度补偿标签的潜在高度解决了这个问题。请看下面我的回答。无论如何,如果您有更好的解决方案,请告诉我!

标签: ios swift xcode uitableview row-height


【解决方案1】:

试试这个:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

编辑

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

斯威夫特 4

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

斯威夫特 4.2

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

定义以上两种方法。
它解决了问题。

PS:此功能需要顶部和底部约束。

Here is example

【讨论】:

  • @bashan 它运行良好。确保你已经给出了适当的约束。
  • 不起作用。如果一个词太长但不够长,似乎有一个错误,它不能正确呈现。如果只是几句话,它似乎可以正常工作。
  • 这对我不起作用,直到我添加了一个底部约束。我认为在您的回答中值得注意的是,必须设置顶部和底部约束才能使其正常工作。
  • 此功能需要上下约束。
  • “单元格元素”的底部和顶部约束是必需的
【解决方案2】:

使用这个:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

不要使用:heightForRowAtIndexPath委托函数

另外,在情节提要中不要设置包含大量数据的标签的高度。给它top, bottom, leading, trailing 约束。

【讨论】:

  • 底部约束很重要!我错过了,想知道为什么无法计算高度。
  • 我要离开这个heightForRowAtIndexPath
  • @Javeed 我认为您可以在任何地方使用它,例如静态单元格或动态单元格..
  • 我不知道为什么这能代替委托函数起作用。不过,谢谢。
【解决方案3】:

SWIFT 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

并且!!! 在故事板中:您必须为标签设置顶部和底部约束。 没有别的了。

【讨论】:

    【解决方案4】:

    这个奇怪的错误是通过 Interface Builder 参数解决的,因为其他答案没有解决这个问题。

    我所做的只是使默认标签大小大于内容可能的大小,并将其反映在 estimatedRowHeight 高度中。以前,我将 Interface Builder 中的默认行高设置为 88px 并在我的控制器 viewDidLoad() 中反映它:

    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = 88.0
    

    但这不起作用。 所以我意识到内容永远不会变得比100px 大,所以我将默认单元格高度设置为108px(大于潜在的内容)并在控制器viewDidLoad()中反映它:

    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = 108.0
    

    这实际上允许代码缩小初始标签到正确的大小。换句话说,它永远不会扩大到更大的尺寸,但总是可以缩小......而且,viewWillAppear() 中不需要额外的self.tableView.reloadData()

    我知道这并不涵盖高度可变的内容大小,但这适用于内容具有最大可能字符数的情况。

    不确定这是否是 Swift 或 Interface Builder 中的错误,但它就像一个魅力。试试看!

    【讨论】:

    • 我也有同样的问题。我已经更新了我的答案。它解决了我的问题。只定义这个方法并删除所有与高度相关的东西。
    【解决方案5】:

    为行高和估计行高设置自动尺寸并确保以下步骤:

    @IBOutlet weak var table: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Set automatic dimensions for row height
        // Swift 4.2 onwards
        table.rowHeight = UITableView.automaticDimension
        table.estimatedRowHeight = UITableView.automaticDimension
    
    
        // Swift 4.1 and below
        table.rowHeight = UITableViewAutomaticDimension
        table.estimatedRowHeight = UITableViewAutomaticDimension
    
    }
    
    
    
    // UITableViewAutomaticDimension calculates height of label contents/text
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // Swift 4.2 onwards
        return UITableView.automaticDimension
    
        // Swift 4.1 and below
        return UITableViewAutomaticDimension
    }
    

    例如:如果你的 UITableviewCell 中有一个标签,那么,

    • 设置行数=0(&换行模式=截尾)
    • 设置与其父视图/单元格容器相关的所有约束(顶部、底部、左右)。
    • 可选:设置标签的最小高度,如果你想要标签覆盖的最小垂直区域,即使没有数据。

    这是具有动态高度限制的示例标签。

    【讨论】:

    • Krunal 提到的 ViewDidLoad() 中的条目是我的解决方案。
    【解决方案6】:

    对于 Swift 3,您可以使用以下内容:

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

    【讨论】:

      【解决方案7】:

      UITableView 的动态调整单元格需要两件事

      1. 在表格视图单元格内设置视图的正确约束(主要包括为视图提供正确的顶部、底部和横向约束)
      2. 在viewDidLoad()中调用TableView的这些属性

         tableView.rowHeight = UITableViewAutomaticDimension
        
         tableView.estimatedRowHeight = 140
        

      This 是一个用 swift 3 编写的关于自动调整大小(动态表格视图单元格)的精彩教程。

      【讨论】:

        【解决方案8】:

        对于 Swift 4.2

        @IBOutlet weak var tableVw: UITableView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
        
            // Set self as tableView delegate
            tableVw.delegate = self
        
            tableVw.rowHeight = UITableView.automaticDimension
            tableVw.estimatedRowHeight = UITableView.automaticDimension
        }
        
        // UITableViewDelegate Method 
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        
            return UITableView.automaticDimension
        }
        

        快乐编码:)

        【讨论】:

          【解决方案9】:

          试试

          override func viewWillAppear(animated: Bool) {
              self.tableView.layoutSubviews()
          }
          

          我遇到了同样的问题,它对我有用。

          【讨论】:

          • 我会试一试,让你知道会发生什么。感谢您的建议!问了将近一年后,除了我自己的答案,我还没有找到任何其他答案!希望你的作品!
          • 确保在调用 layoutsubviews 之前调用 super.viewWillAppear(animated)
          【解决方案10】:

          要使 UITableViewCell 的自动调整大小起作用,请确保您正在进行这些更改:

          • 在 Storyboard 中,您的 UITableView 应该只包含动态原型单元格(它不应该使用静态 单元格)否则自动调整大小将不起作用。
          • 在 Storyboard 中,您的 UITableViewCell 的 UILabel 已配置所有 4 个约束,即顶部、底部、 前导和尾随约束。
          • 在 Storyboard 中,您的 UITableViewCell 的 UILabel的行数应该是0
          • 在你的 UIViewController 中 在 UITableView 属性下设置 viewDidLoad 函数:

            self.tableView.estimatedRowHeight = <minimum cell height> 
            self.tableView.rowHeight = UITableViewAutomaticDimension
            

          【讨论】:

          • 如何使用静态单元格实现相同的功能?
          • 在尝试了这里提供的所有解决方案之后,只有这个(将&lt;minimum cell height&gt; 设置为estimatedRowHeight)真正解决了我的问题。在此之前,单元格会自动调整大小,但我也收到了各种约束警告。现在我没有!所以,非常感谢你,安舒尔!!
          【解决方案11】:

          对于 Swift,我在 iOS 9.0 和 iOS 11 中也检查了这个答案(Xcode 9.3)

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

          这里需要添加上下左右约束

          【讨论】:

            【解决方案12】:

            我用这些

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

            【讨论】:

              【解决方案13】:

              就我而言 - 在情节提要中,我有两个标签,如下图所示, 两个标签都设置了所需的宽度值,然后才使其相等。一旦你取消选择,它就会变成自动的,像往常一样,下面的东西应该像魅力一样工作。

              1.rowHeight = UITableView.automaticDimension, and
              2.estimatedRowHeight = 100(In my case).
              3.make sure label number of lines is zero.
              

              【讨论】:

                【解决方案14】:

                除了别人说的,

                设置标签相对于 SUPERVIEW 的约束!

                因此,与其将标签的约束相对于它周围的其他事物放置,不如将其约束到表格视图单元格的内容视图。

                然后,确保你的标签的高度设置为大于等于0,行数设置为0。

                然后在ViewDidLoad添加:

                tableView.estimatedRowHeight = 695
                
                tableView.rowHeight = UITableViewAutomaticDimension
                

                【讨论】:

                • 设置您的标签相对于 SUPERVIEW 的约束!:节省了我的时间!谢谢。
                【解决方案15】:

                做两件事很简单:

                1. 设置自动高度
                tableView.rowHeight = UITableView.automaticDimension
                
                1. 从上到下创建具有 FULL 约束的所有 TableViewCell。最后一个元素必须定义一些底部间距以结束单元格。

                因此布局引擎可以计算单元格高度并正确应用该值。

                【讨论】:

                • 如果你只是在中西部正确地发音,你就不会犯“heigth”的错误。接下来是什么 - “重量”??
                【解决方案16】:

                我只是受到您的解决方案的启发并尝试了另一种方法。

                请尝试将tableView.reloadData() 添加到viewDidAppear()

                这对我有用。

                我认为滚动背后的东西与 reloadData “相同”。当你滚动屏幕时,就像在viewDidAppear 时调用reloadData()

                如果可行,请回复此答案,以便我确定此解决方案。

                【讨论】:

                • 我会尝试更新它,看看它是否创建了相同的解决方案。谢谢!
                • 对不起康,奇怪的是它对布局没有影响。它将它们保留为在 Interface Builder 中设置的静态值,而不是将它们收缩到适当的大小。
                【解决方案17】:

                不幸的是,我不确定我错过了什么。上述方法不适用于我获取 xib 单元格的高度或让 layoutifneeded() 或 UITableView.automaticDimension 进行高度计算。我一直在寻找和尝试 3 到 4 个晚上,但找不到答案。 不过,这里或另一篇文章中的一些答案确实为我提供了解决方法的提示。这是一种愚蠢的方法,但它有效。只需将所有单元格添加到数组中。然后在 xib 故事板中设置每个高度约束的出口。最后,将它们添加到 heightForRowAt 方法中。如果您不熟悉这些 API,这很简单。

                斯威夫特 4.2

                CustomCell.Swift

                @IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
                @IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
                @IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!
                
                @IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
                @IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!
                

                MyTableViewVC.Swift

                .
                .
                var myCustomCells:[CustomCell] = []
                .
                .
                override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                    let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell
                
                .
                .
                myCustomCells.append(cell)
                return cell
                
                }
                
                
                override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                
                   let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant +  myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant
                
                  return totalHeight + 40 //some magic number
                
                
                }
                

                【讨论】:

                  【解决方案18】:

                  您应该为单元格视图/视图上的每个对象设置 TOPBOTTOMHEIGHT 的所有约束并删除存在 中间 Y 位置(如果有)。因为在你没有这样做的地方,将工件放在另一个视图上。

                  【讨论】:

                  • 嗨!,这个答案可能很好,但最好提供一个工作示例来解释和演示您的答案。
                  【解决方案19】:

                  对于目标 c,这是我很好的解决方案之一。它对我有用。

                  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
                      cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row];
                      cell.textLabel.numberOfLines = 0;
                      cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
                  }
                  
                  - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
                      return UITableViewAutomaticDimension;
                  }
                  

                  我们需要应用这 2 个更改。

                  1)cell.textLabel.numberOfLines = 0;
                    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
                  
                  2)return UITableViewAutomaticDimension;
                  

                  【讨论】:

                    【解决方案20】:

                    我最初也遇到过这个问题,我已经通过这段代码解决了我的问题 尝试避免使用self.tableView.reloadData() 而不是此代码来获取动态高度

                    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
                    

                    【讨论】:

                      【解决方案21】:

                      当使用静态UITableView时,我设置了UILabels中的所有值,然后调用tableView.reloadData()

                      【讨论】:

                        【解决方案22】:
                        self.tableView.rowHeight = UITableViewAutomaticDimension
                        self.tableView.estimatedRowHeight = 88.0
                        

                        别忘了为标签添加底部约束

                        【讨论】:

                          【解决方案23】:
                          self.Itemtableview.estimatedRowHeight = 0;
                          self.Itemtableview.estimatedSectionHeaderHeight = 0;
                          self.Itemtableview.estimatedSectionFooterHeight = 0;
                          
                          
                          [ self.Itemtableview reloadData];
                          self.Itemtableview.frame = CGRectMake( self.Itemtableview.frame.origin.x,  self.Itemtableview.frame.origin.y,  self.Itemtableview.frame.size.width,self.Itemtableview.contentSize.height + self.Itemtableview.contentInset.bottom + self.Itemtableview.contentInset.top);
                          

                          【讨论】:

                          • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
                          【解决方案24】:

                          Swift 5 享受

                          tablev.rowHeight = 100
                          tablev.estimatedRowHeight = UITableView.automaticDimension
                          
                          
                          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                              let cell = self.tablev.dequeueReusableCell(withIdentifier: "ConferenceRoomsCell") as! ConferenceRoomsCell
                              cell.lblRoomName.numberOfLines = 0
                              cell.lblRoomName.lineBreakMode = .byWordWrapping
                              cell.lblRoomName.text = arrNameOfRooms[indexPath.row]
                              cell.lblRoomName.sizeToFit()
                              return cell
                          }
                          

                          【讨论】:

                            【解决方案25】:

                            设置适当的约束并将委托方法更新为:

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

                            这将解决动态单元格高度问题。如果不是,您需要检查约束。

                            【讨论】:

                            • 与同一页面上的Ahmed Lotfy's answer 相同的代码...
                            • 嗯,我已经检查了 swift 3.*,我错过了 Ahmed ans
                            • 您还必须提供估计的行高才能使代码正常工作
                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2020-12-06
                            • 2019-08-15
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多