对 contentView 边缘设置约束会破坏 UITableViewCell 的布局与砌体

Setting constraints on contentView edges breaks layout of UITableViewCell with masonry

我正在尝试创建一个 table 视图单元格,左侧是图像,右侧是内容框。图像应为正方形且占单元格宽度的 20%,内容框(下面代码中的 background)应至少与图像一样大。最后,我想尊重 table 视图本身的布局边距。

除最后一步外,此方法运行良好,尊重 table 视图的边距。当 table 视图较宽时,设置此项会导致我的内容框设置得过大或过小。

// Base class
    [self.background setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];

    [self.background mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.contentView).with.offset(8.0).with.priorityMedium();
        make.trailing.equalTo(self.contentView).with.offset(-8.0).with.priorityMedium();
        make.top.equalTo(self.contentView).with.offset(4.0);
        make.bottom.equalTo(self.contentView).with.offset(-4.0);
    }];

    // **** This block results in respecting tableview margins, but height constraints of background are not respected.  Comment it out to create image "B".
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.mas_leadingMargin);
        make.trailing.equalTo(self.mas_trailingMargin);
        make.top.equalTo(self.mas_top).with.priorityHigh();
        make.bottom.equalTo(self.mas_bottom).with.priorityHigh();
    }];
    // **** End problematic block

// Subclass
    [self.courseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.contentView).with.offset(8.0);
        make.height.and.width.equalTo(self.contentView.mas_width).multipliedBy(.20).with.priorityHigh();
        make.centerY.equalTo(contentView);
    }];
    [self.background mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.courseImageView.mas_trailing).with.offset(8.0);
        make.height.greaterThanOrEqualTo(self.courseImageView).with.priorityMedium();
        make.height.equalTo(self.courseImageView).with.priorityLow();
    }];

A.) 在这里,内容框的高度是正确的,但没有考虑边距

B.) 在这里,边距得到尊重,但 background 已经扩大到一个荒谬的数量。此外,table 视图在像这样重新加载时会向上滚动。

您需要检查 Masonry 默认应用的优先级是什么。他们的文档没有明确说明这一点。

Masonry - Learn to Priortize

第 1 步

尝试在有问题的块内为 leading / trailing 设置高优先级-

// **** This block results in respecting tableview margins, but height constraints of background are not respected.  Comment it out to create image "B".
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.mas_leadingMargin).with.priorityHigh();
        make.trailing.equalTo(self.mas_trailingMargin).with.priorityHigh();
        make.top.equalTo(self.mas_top).with.priorityHigh();
        make.bottom.equalTo(self.mas_bottom).with.priorityHigh();
    }];
    // **** End problematic block

第 2 步

尝试在 cell.contentView 上设置 backgroundColor,看看它在您的案例 A 和 B 中延伸了多远。这会给您一个更好的主意。

第 3 步(不推荐的方法,最坏的情况)

没有任何结果。

  • 将 table 的 leading/trailing 部分 layoutMargins 重置为 0
  • 在子类的 cell.contentView 内添加一个新的 wrapperView 并将其 leading/trailing 设置为预期值。
  • 如果您不想添加 wrapperView,请使用预期的 leading/trailing 值作为 cell.contentView 内所有组件的 leading/trailing 的直接值。

最终,如果结果不如预期,这完全取决于您的选择。有时我不得不在#3 安顿下来。希望对你有帮助。

最后,代码当然完全按照我的指示去做。上面的代码将高度(大于或)设置为等于 table 视图单元格宽度的 20%。然而,这在设置高度时忽略了布局边距,导致了奇怪的行为。

除此之外,我不认为在父class中对contentView添加约束是correct/necessary。简单地添加 availableWidth 视图解决了我在 iPad 上的问题,但在 iPhone 上布局再次中断。为了使两个平台都能正确布局,我必须如下更改基本 class 约束。

这是我更新后的代码:

// Base Class
    [self.background mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.contentView.mas_leadingMargin).with.priorityMedium();
        make.trailing.equalTo(self.contentView.mas_trailingMargin).with.priorityMedium();
        make.top.equalTo(self.contentView.mas_top).with.offset(4.0);
        make.bottom.equalTo(self.contentView.mas_bottom).with.offset(-4.0);
    }];
// *** Constraints on self.contentView are not necessary to respect the default margins! ***

// Subclass
    ...
    UIView *availableWidth = [UIView new];
    availableWidth.hidden = YES;
    [self.contentView addSubview:availableWidth];

    [self.courseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.contentView.mas_leadingMargin);
        make.height.and.width.equalTo(availableWidth.mas_width).multipliedBy(.20);
        make.centerY.equalTo(contentView);
    }];
    [self.background mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.courseImageView.mas_trailing).with.offset(8.0);
        make.height.greaterThanOrEqualTo(availableWidth.mas_width).multipliedBy(.20).with.priorityHigh();
    }];
    [availableWidth mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.equalTo(self.contentView.mas_leadingMargin);
        make.trailing.equalTo(self.contentView.mas_trailingMargin);
        make.height.equalTo(@0);
        make.top.equalTo(self.contentView);
    }];