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

时间:2014-08-01 20:12:20

标签: ios objective-c uitableview autolayout

我有一个包含多行标签的UITableViewCell子类,我希望单元格根据该标签的内容动态调整大小。我知道iOS 8引入了基于AutoLayout约束的自动调整大小的单元格,并且我已经在SO上找到了几个这样的例子,但是我仍然在正确实现这种行为方面遇到了一些麻烦。 / p>

这是我的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,是问题的原因,但我不太确定它到底在哪里来自,希望有人可以对这个问题有所了解。

3 个答案:

答案 0 :(得分:10)

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

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

    确保您已在两个维度中定义了约束的轴向链,即从视图的一个边缘到另一个边缘共同绑定的约束。确保这些约束正确的最简单方法可能是将您的自定义内容实现为普通的UIView(易于测试),然后使用约束以便查看UITableViewCell.contentView拥抱。 (我使用this gist自动构建"视图包装单元格"。)

  2. 设置tableView.rowHeight = UITableViewAutomaticDimension

  3. 设置tableView.estimatedRowHeight = 400或其他一些相当慷慨的值,以便在估算值过低时解决一些UIKit错误。
  4. 我花费了大量时间使用此功能。 This github repo显示了自我调整表格视图单元格的七个完整示例,其中包含一个包装文本的标签 - 程序化,基于nib,基于故事板等。

    最后,如果你看到关于不可满足的约束的警告提及" UIView-Encapsulated-Layout-Height"请不要太担心。或者在第一次加载表视图时类似。这是UITableView创建单元格的初始过程,确定其基于自动布局约束的大小,并保持UITableViewCell紧密的人工制品包裹它的contentView。我上面提到的repo有更广泛的讨论和代码,用于探索API的这个有点尴尬的角落。

    如果它们在单元格已加载并且滚动了一点之后仍然存在,或者如果您最初看到不正确的布局,则应该只担心约束违规警告。在这种情况下,第一步应该始终是通过开发它们并在可能的情况下单独测试它们来确保您的约束是正确的UIView

答案 1 :(得分:4)

我刚刚遇到过这个问题。

从其他许多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);
}

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

这对你有用吗?

答案 2 :(得分:2)

您确定在单元格上将-translatesAutoresizingMaskIntoConstraints设置为NO吗?如果不这样做,系统会根据自动调整掩码生成约束,这是在iOS上进行布局的先前方法,在使用自动布局时应该禁用。