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


当前回答

我必须使用动态视图(通过代码设置视图和约束),当我想设置preferredMaxLayoutWidth标签的宽度为0时。所以我有错误的细胞高度。

然后我添加了

[cell layoutSubviews];

执行之前

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

之后,标签的宽度符合预期,动态高度计算正确。

其他回答

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

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

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

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

动态表视图单元格高度和自动布局

解决故事板自动布局问题的好方法:

- (CGFloat)heightForImageCellAtIndexPath:(NSIndexPath *)indexPath {
  static RWImageCell *sizingCell = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sizingCell = [self.tableView dequeueReusableCellWithIdentifier:RWImageCellIdentifier];
  });

  [sizingCell setNeedsLayout];
  [sizingCell layoutIfNeeded];

  CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
  return size.height;
}

如果您以编程方式进行布局,以下是在Swift中使用锚的iOS 10需要考虑的问题。

有三个规则/步骤

数字1:在viewDidLoad上设置tableview的这两个财产,第一个属性告诉表视图应该期望其单元格的动态大小,第二个属性只是让应用程序计算滚动条指示器的大小,这样有助于提高性能。

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 100

第二:这一点很重要。您需要将子视图添加到单元格的contentView中,而不是添加到视图中,还需要使用其layoutsmargingguide将子视图锚定到顶部和底部,这是一个很好的示例。

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setUpViews()
}

private func setUpViews() {

    contentView.addSubview(movieImageView)
    contentView.addSubview(descriptionLabel)
    let marginGuide = contentView.layoutMarginsGuide

    NSLayoutConstraint.activate([
        movieImageView.heightAnchor.constraint(equalToConstant: 80),
        movieImageView.widthAnchor.constraint(equalToConstant: 80),
        movieImageView.leftAnchor.constraint(equalTo: marginGuide.leftAnchor),
        movieImageView.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 20),

        descriptionLabel.leftAnchor.constraint(equalTo: movieImageView.rightAnchor, constant: 15),
        descriptionLabel.rightAnchor.constraint(equalTo: marginGuide.rightAnchor),
        descriptionLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor, constant: -15),
        descriptionLabel.topAnchor.constraint(equalTo: movieImageView.topAnchor)

        ])
}

创建一个将添加子视图并执行布局的方法,在init方法中调用它。

第3:不要调用方法:

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

如果你这样做,你将覆盖你的实现。

对于表视图中的动态单元格,请遵循以下3条规则。

这是一个有效的实现https://github.com/jamesrochabrun/MinimalViewController

我必须使用动态视图(通过代码设置视图和约束),当我想设置preferredMaxLayoutWidth标签的宽度为0时。所以我有错误的细胞高度。

然后我添加了

[cell layoutSubviews];

执行之前

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

之后,标签的宽度符合预期,动态高度计算正确。

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

分配和实现表视图数据源和委托将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)具有动态长度,应根据其内容大小进行调整:请调整要以更高优先级展开/压缩的标签的“内容拥抱和抗压优先级”。