对 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 默认应用的优先级是什么。他们的文档没有明确说明这一点。
第 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);
}];
我正在尝试创建一个 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 默认应用的优先级是什么。他们的文档没有明确说明这一点。
第 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);
}];