如何在表视图中的UITableViewCells中使用“自动布局”,让每个单元格的内容和子视图确定行高度(自身/自动),同时保持平滑的滚动性能?


当前回答

像@Bob Spryn一样,我遇到了一个非常重要的问题,我把这个问题作为答案发布。

我纠结于@smileyborg的回答了一会儿。我遇到的问题是,如果您在IB中使用其他元素(UILabels、UIButtons等)定义了原型单元,当您使用[[YourTableViewCellClass alloc]init]实例化该单元时,它不会实例化该单元中的所有其他元素,除非您编写了这样做的代码。(我对initWithStyle有过类似的经历。)

要让故事板实例化所有其他元素,请使用[tableView dequeueReusableCellWithIdentifier:@“DoseNeed”](不是[tableView de queueReusable CellWithIdentifier:forIndexPath:],因为这会引起有趣的问题。)执行此操作时,将实例化IB中定义的所有元素。

其他回答

@smileyborg提出的解决方案几乎是完美的。如果您有一个自定义单元格,并且需要一个或多个具有动态高度的UILabel,则systemLayoutSizeFittingSize方法与启用自动布局相结合将返回一个CGSizeZero,除非您将所有单元格约束从单元格移到其contentView(如@TomSwift在这里建议的那样,如何调整超视图的大小以适应具有自动布局的所有子视图?)。

为此,您需要在自定义UITableViewCell实现中插入以下代码(感谢@Adrian)。

- (void)awakeFromNib{
    [super awakeFromNib];
    for (NSLayoutConstraint *cellConstraint in self.constraints) {
        [self removeConstraint:cellConstraint];
        id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
        id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;
        NSLayoutConstraint *contentViewConstraint =
        [NSLayoutConstraint constraintWithItem:firstItem
                                 attribute:cellConstraint.firstAttribute
                                 relatedBy:cellConstraint.relation
                                    toItem:seccondItem
                                 attribute:cellConstraint.secondAttribute
                                multiplier:cellConstraint.multiplier
                                  constant:cellConstraint.constant];
        [self.contentView addConstraint:contentViewConstraint];
    }
}

将@smileyborg答案与此混合应该会奏效。

Swift中的另一个iOs7+iOs8解决方案

var cell2height:CGFloat=44

override func viewDidLoad() {
    super.viewDidLoad()
    theTable.rowHeight = UITableViewAutomaticDimension
    theTable.estimatedRowHeight = 44.0;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell =  tableView.dequeueReusableCellWithIdentifier("myTableViewCell", forIndexPath: indexPath) as! myTableViewCell
    cell2height=cell.contentView.height
    return cell
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if #available(iOS 8.0, *) {
        return UITableViewAutomaticDimension
    } else {
        return cell2height
    }
}

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

分配和实现表视图数据源和委托将UITableViewAutomaticDimension分配给rowHeight和estimatedRowHeight实现委托/dataSource方法(即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(换行模式=截断尾部(&L)设置与其超级视图/单元格容器相关的所有约束(顶部、底部、左右)。可选:如果您希望标签覆盖最小垂直区域,即使没有数据,也可以设置标签的最小高度。

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

只要你的单元格布局良好。

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];

    return [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
}

更新:您应该使用iOS 8中引入的动态调整大小。

UITableView.automaticDimension可以通过接口生成器设置:

Xcode>情节提要>尺寸检查器

表格视图单元格>行高度>自动