在iOS 8中自动调整UITableViewCell的大小

我有一个UITableViewCell子类,其中包含一个多行标签,我希望单元格根据该标签的内容dynamic调整自己的大小。 我知道,iOS 8引入了基于AutoLayout约束的自动resize的单元格,并且我已经发现了几个这样的例子,但是我仍然在实现这种行为时遇到了一些麻烦。

这是我的updateConstraints实现:

- (void)updateConstraints { [super updateConstraints]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_nameLabel(==20)]-10-[_tweetLabel]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_nameLabel, _tweetLabel)]]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_avatarView]-10-[_nameLabel]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView, _nameLabel)]]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_nameLabel]-10-[_tweetLabel]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_nameLabel, _tweetLabel)]]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_avatarView]-10-[_tweetLabel]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView, _tweetLabel)]]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[_avatarView(==45)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView)]]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[_avatarView(==45)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_avatarView)]]; } 

在表视图控制器中,我将行高设置为UITableViewAutomaticDimension(并设置了估计的行高度)。 在运行时,我得到一系列的自动布局错误,所有的表格视图单元格几乎完全重叠。

自动布局冲突在以下约束之间:

  • V:|-(10)-[_nameLabel]
  • V:[_nameLabel(20)]
  • V:[_nameLabel]-(10)-[_tweetLabel]
  • V:[_tweetLabel]-(10)-|
  • V:[cell(44)]

我怀疑最后一个约束“UIView-Encapsulated-Layout-Height”,这个约束高度为44的问题是这个问题的原因,但是我不太确定这个问题是从哪里来的,所以希望有人能够阐明一下。问题。

为了实现表格视图单元格的自动行高,您需要执行以下操作:

  1. 在单元格的contentView中实现自动布局约束,允许视图表示它的首选高度。 确保将UILabel设置为多行换行。

    确定你已经在两个维度上定义了一个轴向的约束链,也就是说,从视图的一个边到另一个边的整个约束。 也许最简单的方法来确定这些约束是正确的是实现你的自定义内容作为一个普通的旧UIView (这是很容易testing),然后使用约束,使UITableViewCell.contentView拥抱该视图。 (我用这个要点来自动构build“视图包装单元”。)

  2. 设置tableView.rowHeight = UITableViewAutomaticDimension

  3. 设置tableView.estimatedRowHeight = 400或其他合理的慷慨价值,以解决一些UIKit错误,当估计过低。

我花费了大量的时间来处理这个function。 这个github回购显示了七个自动resize的表格视图单元格的完整示例,其中包含单个标签的包装文本 – 基于编程,基于笔尖,基于故事板的等等。

最后,如果在第一次加载表视图时看到提及“UIView-Encapsulated-Layout-Height”或类似的不可满足的约束的警告,不要太担心。 这是UITableView创build单元格的初始过程的一个假象,根据自动布局约束来确定其大小,并保持UITableViewCell紧紧地包装其contentView 。 我上面提到的回购有更广泛的讨论和代码来探索API的这个有点尴尬的angular落。

如果在单元格加载并滚动一下之后仍然存在约束违规警告,或者您最初看到错误的布局,则应该只考虑违反约束的警告。 在这种情况下,第一步应该始终是通过开发它们并在可能的情况下单独testing它们来确保约束是正确的,在一个普通的UIView

我刚刚遇到这个问题。

从许多其他的Stackoverflow文章他们推荐:

 self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; 

起初这不适合我。 我发现我也需要这样做

 self.frame = CGRectMake(0, 0, self.frame.size.width, 50); 

我的自定义单元格的init方法看起来像他的:

 -(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if(self) { [self initViews]; [self initConstraints]; } return self; } 

我把代码放在我的“initViews”方法中:

 -(void)initViews { ... // fixes an iOS 8 issue with UIViewEncapsulated height 44 bug self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, 50); } 

问题消失了,我的细胞看起来也是正确的。

这对你有用吗?

你确定你有–translatesAutoresizingMaskIntoConstraints设置为否在单元格? 如果不这样做,则系统会根据自动调整屏蔽来生成约束,这是以前在iOS上进行布局的方式,在使用自动布局时应该禁用。