在 TableViewCell 中自动布局两个标签?

Posted

技术标签:

【中文标题】在 TableViewCell 中自动布局两个标签?【英文标题】:AutoLayout two labels within a TableViewCell? 【发布时间】:2013-12-10 03:16:11 【问题描述】:

我对 ios 编程相当陌生,可能不了解视图层次结构,因此无法在我创建的自定义表格单元格类中成功获取两个标签以正确调整大小。即"translatesAutoresizingMaskIntoConstraints" 属性让我有点困惑。

我没有为这部分代码使用故事板:我有一个 TableViewController,我在 viewDidLoad 中创建了我自己的 tableView。在cellForRowAtIndexPath 中,我初始化了我自己的TableViewCell 实现。

我遇到的问题是,当我将表视图的 "setTranslatesAutoresizingMaskIntoConstraints" 设置为 NO 和我创建的 UILabels 然后添加我的约束时,我收到以下错误:

"Terminating app due to uncaught exception `'NSInternalInconsistencyException',` reason: 'Auto Layout still required after executing `-layoutSubviews`. UITableView's implementation of `-layoutSubviews` needs to call super.'"

如果我注释掉 setTranslatesAutoresizingMaskIntoConstraints 行,我的应用程序会运行,但是我会收到以下关于约束的警告:

“不能同时满足约束。可能至少有一个 以下列表中的约束是您不想要的。尝试 这个:(1)查看每个约束并尝试找出你 不要期待; (2) 找到添加了不需要的约束的代码或 约束并修复它。 (注:如果你看到 NSAutoresizingMaskLayoutConstraints 不明白的可以参考 UIView 属性的文档 translatesAutoresizingMaskIntoConstraints)"

基本上我想要做的是在此处输入代码,使两个标签彼此齐平,并根据方向/设备调整它们的大小(我将在它们上设置背景颜色,因此希望它们看起来“连续” )

谁能帮我解释一下我错过了什么?提前致谢。

我添加标签的代码是:

self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 30.0f)];
self.nameLabel.textColor = [UIColor redColor];
self.nameLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:12.0f];
self.nameLabel.backgroundColor = [UIColor brownColor];
[self.nameLabel setText:@"Test"];
// [self.nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:self.nameLabel];

...

NSDictionary *viewsDictionary = 
 NSDictionaryOfVariableBindings(nameLabel, summaryLabel);
NSArray *constraints = 
 [NSLayoutConstraint constraintsWithVisualFormat:@"|-[nameLabel][summaryLabel]-|" 
                                         options:0 
                                         metrics:nil 
                                           views:viewsDictionary];

【问题讨论】:

您的updateConstraints 方法和您的layoutSubviews 方法会发生什么?你打电话给[super layoutSubviews] hmm,根据这个:developer.apple.com/library/ios/documentation/UserExperience/… 你不应该调用 setTranslatesAutoresizingMaskIntoConstraints:NO(见文章最后一段) 感谢@Evan,但是我没有在我创建的自定义单元类中覆盖这些方法,因此不确定错误是什么.. @Yohst:我看到了,这是否意味着我不能在自己的表格单元实现中使用自动布局?我希望我误解了这一点。 我不认为你应该为表格视图设置 translatesAutoresizingMaskIntoConstraints 为 no,只为标签设置。 【参考方案1】:

我对 ios 编程相当陌生,可能不了解 视图层次结构以及我应该,因此未能成功 在我创建的自定义表格单元格类中获取两个标签 自动调整大小。即 “setTranslatesAutoresizingMaskIntoConstraints”属性有我 有点困惑。

好吧,translatesAutoresizingMaskIntoConstraints 是 Apple 创建的一个属性,用于使从 Autoresizing (Spring and Struts)Autolayout 的转换更容易。比如说,您有一些 AutoresizingMasks 供您查看,而您只是在没有设置任何约束的情况下将 Autolayout 切换为 ON。然后,您现有的AutoresizingMasks 将被转换为约束,将视图保持在适当的位置。因此,默认情况下 translatesAutoresizingMaskIntoConstraints 属性设置为 YES。但是,当您开始添加约束时,在 90% 的情况下,它们会与通过转换您的 AutoresizingMasks 创建的约束发生冲突。所以,最好通过设置view.translatesAutoresizingMaskIntoConstraints = NO来关闭它

在您的代码中,可能存在以下问题:


Frame的设置

您不应该为要添加约束的对象设置框架。这是一种范式转变。当您以 Autolayout 方式 思考时,框架只是设置正确约束的效果,这些约束共同决定了相关视图的框架。 所以,请删除框架设置。

self.nameLabel = [[UILabel alloc] init]; 就足够了。

设置适当的约束

您的代码:


NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(nameLabel, summaryLabel);
NSArray *constraints = 
 [NSLayoutConstraint constraintsWithVisualFormat:@"|-[nameLabel][summaryLabel]-|" 
                                         options:0 
                                         metrics:nil 
                                           views:viewsDictionary];

姓名标签

现在,上面的约束告诉我们nameLabel 应该是水平(因为你没有提到 H: 或 V:)与容器的“标准”距离 (20px),与容器相邻summaryLabel。 但是它的 Y 位置和宽度和高度呢? 所以我们需要更多的约束。

summaryLabel

同样适用于summaryLabel

所以,让我们正确定义它们:

NSDictionary *viewsDictionary =
NSDictionaryOfVariableBindings(nameLabel, summaryLabel);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[nameLabel(100)][summaryLabel]-|" options:0 metrics:nil views:viewsDictionary];
NSArray *constraints1 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[nameLabel(30)]" options:0 metrics:nil views:viewsDictionary];
NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[summaryLabel]" options:0 metrics:nil views:viewsDictionary];
NSArray *constraints3 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[nameLabel(==summaryLabel)]" options:0 metrics:nil views:viewsDictionary];


[self.view addConstraints:constraints];
[self.view addConstraints:constraints1];
[self.view addConstraints:constraints2];
[self.view addConstraints:constraints3];

现在您的视图看起来会很好。


在任何时候,要检查您的视图是否缺少任何约束,请暂停调试器并在控制台中键入以下内容

po [[UIWindow keyWindow] _autolayoutTrace]

它将显示您的哪些视图拥有AMBIGUOUS LAYOUT

另外,请记住在 Storyboard/IB 中,如果约束显示为“橙色”颜色,则需要更多约束来定义对象位置。添加所有必要的约束后,约束颜色会变为“蓝色”

【讨论】:

【参考方案2】:

首先,你是否在创建后给 self.contentView 添加约束?

其次,也许你的约束集不足以自动布局,它会根据自动调整掩码创建自己的约束。尝试为标签添加垂直约束和宽度约束。

【讨论】:

以上是关于在 TableViewCell 中自动布局两个标签?的主要内容,如果未能解决你的问题,请参考以下文章

标签显示超出我的自定义 TableViewCell 范围并通过 swift 设置自动布局

自定义 TableViewCell 中忽略自动布局

自定义 tableviewcell 动态高度未根据约束更新(以编程方式自动布局)

iOS 自动布局和拥抱内容

故事板中自动布局标签的表格视图单元格约束[关闭]

如何使 tableviewcell 高度自动增长