为什么 UITableViewAutomaticDimension 不工作?

why UITableViewAutomaticDimension not working?

您好,有很多问题回答 UITableViewCellUITableView 的动态高度。但是我做的时候觉得很奇怪。

以下是部分答案:

and here

通常这会回答单元格的动态高度

tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableView.automaticDimension

但在我的情况下,我想知道这条线不会做任何事情。

我的 UITableView 在点击 splitview 内的标签栏后被查看。这有帮助吗?

也许我漏掉了什么。谁能帮帮我我花了2个小时做傻事。

这些是我对标题的限制标题可以很长但标签不是。

这是我的手机

为了使 UITableViewAutomaticDimension 正常工作,您必须设置所有与单元格容器视图相关的左、右、下和上约束。在您的情况下,您需要将缺少的底部 space 添加到 title

下标签的 superview 约束

还要确保单元格中 UILabel 的线条设置为 0。如果设置为 1,它将不会垂直增长。

我以编程方式添加了约束,不小心将它们直接添加到单元格中,即不在 contentView 属性 上。将约束添加到 contentView 为我解决了!

在我的例子中,我有两个 UITableView,我必须将此方法修改为

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    CGFloat height = 0.0;
    if (tableView == self.tableviewComments) {
        return UITableViewAutomaticDimension;
    }else if (tableView == self.tableViewFriends) {
        height = 44.0;
    }
    return height;
}

忘记删除tableView(heightForRowAt:indexPath:)

您可能像我一样,不小心忘记删除 heightForRowAt 方法的样板代码。

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

我有一个具体案例,我阅读的 99% 的解决方案都不起作用。我想我会分享我的经验。希望它能有所帮助,因为在解决此问题之前我已经挣扎了几个小时。

我的场景

  • 我在一个 中使用两个 TableView ViewController
  • 我正在在这些表格视图中加载自定义单元格 (xib)
  • 单元格中的动态内容由两个标签组成
  • 页面使用 ScrollView

我需要达到的目标:

  • 动态 TableView 高度
  • 动态 TableViewCells 高度

您需要检查什么才能使其顺利运行:

  • 就像每个教程和答案都会告诉您的那样,为您的 label/content(顶部、底部、前导和尾随)设置所有约束,并将其设置到 ContentView(Superview)。 This video tutorial will be helpful.

  • 在我的 ViewController 的 viewWillAppear 方法中,我给了我的一个 tableView (tableView2) 一个估计的行高,然后使用 UITableViewAutomaticDimension 本身(以及所有 tutorials/answers 中所见):

        override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    
        tableView2.estimatedRowHeight = 80
        tableView2.rowHeight = UITableViewAutomaticDimension
    
    }
    

对我来说,前面的这些步骤还不够。我的 TableView 将简单地采用 estimatedRowHeight 并将其乘以单元格数。嗯。

  • 因为我使用了两个不同的 tableView,所以我为它们各自创建了一个出口,tableView1tableView2。允许我在 viewDidLayoutSubviews 方法中调整它们的大小。欢迎在评论中询问我是如何做到的。

  • 通过将其添加到 viewDidAppear 方法中,我需要执行一个额外的步骤来修复它:

    override func viewDidAppear(_ animated: Bool) {
    tableView1.reloadData() // reloading data for the first tableView serves another purpose, not exactly related to this question.
    tableView2.setNeedsLayout()
    tableView2.layoutIfNeeded()
    tableView2.reloadData()
    }
    

希望对某人有所帮助!

为了使 UITableViewAutomaticDimension 正常工作,您需要确保将所有 4 个角的约束都添加到超级视图中。在大多数情况下,它与 UILabel 配合使用效果很好,但有时我发现 UITextView 在 UILabel 无法正常工作时发挥作用。所以尝试切换到 UITextView 并确保 Scrolling Enabled 在情节提要中未选中,或者您也可以通过编程方式设置它。

要为行高和估计行高设置自动尺寸,请确保按照以下步骤制作,自动尺寸对 cell/row 高度布局有效。

  • 分配并实现表视图数据源和委托
  • UITableViewAutomaticDimension 分配给 rowHeight & estimatedRowHeight
  • 实施delegate/dataSource方法(即heightForRowAt和return一个值UITableViewAutomaticDimension

-

Objective C:

// in ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

  @property IBOutlet UITableView * table;

@end

// in ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    self.table.dataSource = self;
    self.table.delegate = self;

    self.table.rowHeight = UITableViewAutomaticDimension;
    self.table.estimatedRowHeight = UITableViewAutomaticDimension;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return UITableViewAutomaticDimension;
}

Swift:

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

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

注意:如果你有多个具有动态长度的标签(UIElements),应根据其内容大小进行调整:调整'Content Hugging and Compression Resistance Priority ` 对于您想要 expand/compress 具有更高优先级的标签。

我有三个水平项目,最左边的项目有向左的约束,中间的项目有顶部、底部、左侧项目和右侧项目。右边的有一个右边,左边到中间的项目。解决方案是向中间项(我的标签)添加额外的左右约束,这些约束 >= 单元格中的某个数字。

试试这个,简单的解决方案对我有用,

在viewDidLoad中写这段代码,

-(void)viewDidLoad 
{
[super viewDidLoad];
 self.tableView.estimatedRowHeight = 100.0; // for example. Set your average height
 self.tableView.rowHeight = UITableViewAutomaticDimension;
}

在cellForRowAtIndexPath中写入这段代码,

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
  static NSString *CellIdentifier = @"Cell";
  UITableViewCell *cell = [tableView 
  dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
  }
    cell.textLabel.numberOfLines = 0; // Set label number of line to 0
    cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"menu"];
    [cell.textLabel sizeToFit]; //set size to fit 
    return cell;
 }

确保单元格中的所有视图都被限制在内容视图中,而不是单元格中。

正如苹果所说:

lay out the table view cell’s content within the cell’s content view. To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge.

截至iOS11和Xcode9.3,以上信息大部分是错误的。 Apple's Guide 建议设置

    tableView.estimatedRowHeight = 85.0
    tableView.rowHeight = UITableViewAutomaticDimension

WWDC 2017 session 245(使用动态类型构建应用程序,视频中大约 16:33)提出了类似的建议。 None 这对我来说很重要。

对于字幕样式单元格,要获得 self-sizing table 视图单元格,只需将行数(在属性检查器的标签部分)设置为 0标题和副标题。如果这些标签之一太长并且您没有将行数设置为 0,则 table 视图单元格不会调整其大小。

对于我的设置,我首先仔细检查了 Storyboard 中的约束,以确保 UITableViewCell 从上到下都没有歧义,然后不得不在 2 个地方修改代码。

  1. UITableViewDelegatetableView(_:heightForRowAt:)

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
        // return UITableViewAutomaticDimension for older than Swift 4.2
    }
    
  2. UITableViewDelegatetableView(_:estimatedHeightForRowAt:)

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
        // return UITableViewAutomaticDimension for older than Swift 4.2
    }
    

第 1 步和第 2 步,让您可以为特定行应用自动调整大小。要应用于整个 UITableView,请使用:

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
// return UITableViewAutomaticDimension for older than Swift 4.2

我有一个新的解决方案..对我有用。

基本上UITableViewAutomaticDimension重命名为UITableView.automaticDimension...我希望..它

对于可能遇到与我相同问题的任何人:我努力了一个小时才让它工作。具有顶部、底部左侧和右侧约束的简单 UIlabel。我使用 willDisplayCell 将数据传递给单元格,这导致单元格高度出现问题。只要我将该代码放入 cellForRow 中,一切都正常。不明白为什么会这样,可能是在调用willDisplayCell之前计算了单元格高度,所以没有内容可以正确计算。我只是想提一下并可能帮助遇到同样问题的人。

它在 iOS 11 及更高版本中对我来说很好用,而在 iOS 10 中 解决方案是添加

table.rowHeight = UITableView.automaticDimension
table.estimatedRowHeight = 200 // a number and not UITableView.automaticDimension

还要确保添加 "heightForRowAt",即使它适用于 iOS 11 及更高版本,如果您支持 iOS 10

,则需要它
   func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

在我的情况下,我做了一切,但没有解决我的问题,最后,我检查了固定为 3 的标签的行。将行值更改为 0 解决了对我来说是个问题。所以告诉你它必须是 0 并且必须附加约束 Top、Bottom、Left、Right 才能正常工作。

一种不常见的解决方案,但可以节省其他人的时间:在 cellForRowAtIndexPath 中确保在设置标签文本时没有延迟。出于某种未知原因,我将它包裹在 DispatchQueue.main.async 块中,这意味着在实际设置标签文本之前返回单元格,因此单元格和标签永远不会扩展到文本的大小。

对于 ios 和 swift 的最新版本,apple 已将之前调用的 UITableView.automaticDimension 更改为 UITableView().estimatedRowHeight,因此要自动设置行高,请像这样使用它: tableView.estimatedRowHeight = 150 //手动随机估计以帮助编译器在设置估计值之前。 tableView.rowHeight = UITableView().estimatedRowHeight