为什么UITableViewAutomaticDimension不起作用?


76

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

这是一些答案:

这里这里

通常这会回答细胞的动态高度

tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension

但就我而言,我想知道这条线不会做任何事情。

UITableView单击splitview内的选项卡后,正在查看我。这有帮助吗?

也许我在想什么。谁能帮助我,我花了2个小时做傻事。

这些是我对标题的限制,标题可能很长,但标签却没有。

在此处输入图片说明

这是我的手机

在此处输入图片说明


2
您应该使用UITableViewCellxib / storyboard中的自动布局设置再次进行重新检查。您那里有一些问题100%
Vitalii Gozhenko 2015年

2
是的,我正在重写它。希望找到导致它的原因
CaffeineShots 2015年

如果您在此处张贴xib / storyboard,我可以为您提供帮助
Vitalii Gozhenko 2015年

您是否设置了相对于单元格内容视图顶部和底部的视图约束?
Zell B.

我应该只截图吗?
CaffeineShots

Answers:


163

为了使UITableViewAutomaticDimension起作用,您必须设置相对于单元格容器视图的所有左,右,下和上约束。在您的情况下,您需要将缺少的底部空间添加到标题下标签的Superview约束中


14
注意,您可能必须将某些视图的底部约束设置为> =而不是=,以使其随单元格的动态高度增长。这是我的把戏。
Ryan R

@khunshan您确定不使用尺寸等级吗?
Zell B.

@ZellB。是的,你是对的。其原因是缺少iPhone类。(Y)
khunshan

28

我已经以编程方式添加了约束,并且无意间将它们直接添加到单元中,即不在contentView属性上。添加约束contentView为我解决了!


是的,我们需要清楚地知道我们对哪些约束缺少或添加了什么约束,可能会导致歧义或不满足约束。感谢答案!
CaffeineShots

我知道这很老,但我不认为这是正确的方法。如果您不将约束添加到内容视图。当您打开单元格的任何编辑样式(如删除)或移动其自身的行时,视图将变形。
Esko918

@ Esko918我认为您读错了他的答案。他说您需要在上添加约束contentView。我也无意加约束的UITableViewCell时候,应该给UITableViewCellcontentView
艾伦

这就是我所说的。如果不将约束添加到内容视图,则当您选择编辑样式(例如删除或移动行)时,视图将变形。您不应该直接修改单元格视图,因为当您进入编辑模式时UIKit会修改单元格布局,并且单元格向右移动。您应该将所有子视图和布局约束添加到内容视图。不是视图本身
Esko918

25

要为行高和估计的行高设置自动尺寸,请确保执行以下步骤,自动尺寸对单元格/行高布局有效。

  • 分配并实现tableview数据源和委托
  • 分配UITableViewAutomaticDimension给rowHeight和估计的RowHeight
  • 实现委托/数据源方法(即向其heightForRowAt返回值UITableViewAutomaticDimension

--

目标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;
}

迅速:

@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(&换行模式=截尾)
  • 设置相对于其superview /单元容器的所有约束(上,下,左左)。
  • 可选:如果您希望标签覆盖最小的垂直区域,即使没有数据,也可以设置标签的最小高度。

在此处输入图片说明

注意:如果您具有多个具有动态长度的标签(UIElements),则应根据其内容大小进行调整:对于要以更高优先级进行扩展/压缩的标签,请调整“内容拥抱和抗压缩优先级”。


通过返回UITableView.automaticDimension工作实现heightForRowAt
Ucdemir

19

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


7

我有一个特定的案例,我阅读的99%的解决方案均无效。我以为我会分享我的经验。希望它能有所帮助,因为在解决此问题之前我已经奋斗了几个小时。

我的场景

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

我需要实现的目标

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

您需要检查以使其顺利运行

  • 就像每个教程和答案都会告诉您的那样,设置标签/内容的所有约束(顶部,底部,前导和尾随),并将其设置为ContentView(超级视图)。该视频教程将对您有所帮助

  • viewWillAppearViewController的方法中,我给了一个tableViews(tableView2)一个估计的行高,然后按UITableViewAutomaticDimension原样使用(在所有教程/答案中都看到了):

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

对我来说,这些先前的步骤还不够。我的TableView会简单地使用估算的RowHeight并将其乘以单元格的数量。ee

  • 由于我使用两种不同的tableViews,我创建了他们每个人的出口,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()
    }
    

希望能对某人有所帮助!


最后的建议(但没有双重IBOutlet)在2019
。– zhukov.ever

6

从iOS 11和Xcode 9.3开始,上述大多数信息都是错误的。 苹果指南建议设置

    tableView.estimatedRowHeight = 85.0
    tableView.rowHeight = UITableViewAutomaticDimension

WWDC 2017会议245(使用动态类型构建应用程序,在视频中大约16:33)提出了类似的建议。这些都对我没有影响。

对于字幕样式单元格,获取自定义表格视图单元格所需要做的就是将“标题”和“字幕”的行数(在属性检查器的“标签”部分中)设置为0。如果这些标签之一太长,并且您未将行数设置为0,则表格视图单元格将不会调整其大小。


设置numberOfLines0这两个标签,让你得到自调整大小非定制UITableViewCell秒。非常感谢!
mxcl

5

忘记删除 tableView(heightForRowAt:indexPath:)

和我一样,您可能偶然忘记了删除heightForRowAt方法的样板代码。

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

...而且当然也不要给它一个高度限制;-)
Marcos

1
您可以UITableViewAutomaticDimension使用此方法返回。对于子类
Yanny

5

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


谢谢!我也为这个问题而苦苦挣扎。对我来说似乎是一个UIKit的错误,但这解决了!
加里·胡珀

4

在iOS 11及更高版本中对我来说工作正常,而在iOS 10中中断时,解决方案是添加

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

还要确保即使在iOS 11及更高版本中也可以添加“ heightForRowAt”,如果支持iOS 10,则需要添加

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

3

以我为例,我有两个UITableViews,我必须将此方法修改为

-(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;
}

3

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

在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;
 }

1

对于我的设置,我首先仔细检查了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

0

为了使UITableViewAutomaticDimension正常工作,您需要确保将所有4个角的约束都添加到超级视图中。在大多数情况下,它可以与UILabel一起很好地工作,但是有时候我发现当UILabel不能很好地工作时,UITextView可以解决问题。因此,请尝试切换到UITextView并确保Scrolling Enabled在情节提要中未选中它,或者您也可以通过编程设置它。


0

我有三个水平项目,最左边有一个约束,中间一个有顶部,底部,左边和右边的约束。右边的一个有右边,而左边是中间的那个。解决方案是向中间项目(我的标签)添加其他左右约束,这些约束大于单元格的某个数字。


0

确保单元格中的所有视图都限于“内容视图”而不是单元格。

正如苹果所说:

在单元格的内容视图内布置表格视图单元格的内容。要定义单元格的高度,您需要一个不间断的约束和视图链(具有定义的高度),以填充内容视图的顶部边缘与其底部边缘之间的区域。


0

我有一个新的解决方案..为我工作。

基本上UITableViewAutomaticDimension改名为UITableView.automaticDimension...,我希望..它


0

在此处输入图片说明在我的情况下,我做了所有事情,但并没有为我解决问题,最后,我检查了固定为3的标签的行。将行值更改为0可以为我解决问题。所以告诉您所有参数都必须为0,并且必须附加上,下,左,右约束才能正常工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.