具有自动布局的 UITableView 中的动态列

Posted

技术标签:

【中文标题】具有自动布局的 UITableView 中的动态列【英文标题】:Dynamic Columns in a UITableView with Auto Layout 【发布时间】:2013-10-15 19:06:21 【问题描述】:

在我的 iPad 应用程序中,我将有一个 UITableView 显示在弹出窗口中。我有多个要显示的值,因此我制作了一个带有多个标签的自定义UITableViewCell,以模拟表格中的许多“列”。我想做的是确保我所有的“列”都排成一行。

问题是,我无法对列的宽度进行硬编码,因为我正在从 XML Web 服务动态填充数据 - 所以在我进行调用之前我不知道它们需要多宽并且收到数据。

我的想法是遍历数据(一旦我得到它),并使用NSStringsizeWithAttributs: 方法来获取我的每一列的最大宽度。然后我会将该宽度发送到我的自定义单元格,以便该单元格可以在其layoutSubviews 方法中使用它。问题是,我正在尝试使用NSLayoutConstraints 来完成所有这些工作,并且在我看到的所有示例中,constraintsWithVisualFormat: 中的任何尺寸都是硬编码的——直到运行时我才知道我的尺寸是多少。我的想法是做类似的事情

NSDictionary *myDictionary = NSDictionaryOfVariableBindings(myLabel1,myLabel2)
NSArray *myConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[myLabel1(%d)]-[myLabel2(%d)]",myWidth1,myWidth2 options:NSLayoutFormatAlignAllBaseline metrics:nil views:myDictionary];

但这会导致构建错误。是否可以在运行时动态地为constraintsWithVisualFormat 提供大小,而不是硬编码?

【问题讨论】:

【参考方案1】:

推荐的做法是使用metrics参数:

NSDictionary *myDictionary = NSDictionaryOfVariableBindings(myLabel1,myLabel2)
NSArray *myConstraints = [NSLayoutConstraint 
          constraintsWithVisualFormat:@"H:|-[myLabel1(lbl1w)]-[myLabel2(lbl2w)]" 
                              options:NSLayoutFormatAlignAllBaseline 
                              metrics:@@"lbl1w": @(myWidth1),
                                        @"lbl2w": @(myWidth2)  
                                views:myDictionary];

这基本上允许您提供将名称映射到数值的字典,以便在可视格式字符串中的任何位置使用。这些值需要是 NSNumber 实例,可以使用去年引入的 @(aVariable) 构造从 C 数值变量轻松构造。

【讨论】:

是否有特别的原因推荐这种方式,而不是使用我的方式?使用这些指标对我来说似乎并不简单(我认为它更复杂)。此外,我不记得看到 metrics 字典用于将值链接到临时变量,只是为了在另一个参数中使用,但我看到了大量传递 [NSString stringWithFormat:@"..."] 而不仅仅是 @"..." 的实例当 NSString 被请求作为输入类型时。我想我只是有点困惑,为什么约束应该以不同的方式完成。 本身并不推荐使用字符串格式。由于自动布局的可视格式解析器无论如何都会进行字符串解析工作,您不妨告诉它用一些名称替换它们的数值。您的方式使字符串解析发生两次。此外,实际名称总是比一堆%d 更具可读性。最后,如果您要多次重复使用相同的值,这种方式将证明自己很方便。 此外,如果您要重用具有不同宽度或边距的视觉格式,或者跨视觉格式重用一组宽度/边距,则会更简洁。值得一试!【参考方案2】:

在我写这篇文章的时候,我有一种不愚蠢的想法,这促使我看看你实际上应该将什么作为constraintsWithVisualFormat 的第一个参数传递给constraintsWithVisualFormat,果然,它只是在寻找一个@ 987654322@。所以解决办法就是简单的把前面的字符串打断:

NSString *formattedString = [NSString stringWithFormat:@"H:|-[myLabel1(%d)]-[myLabel2(%d)]",myWidth1,myWidth2];

然后传入:

NSArray *myConstraints = [NSLayoutConstraint constraintsWithVisualFormat:formattedString options:NSLayoutFormatAlignAllBaseline metrics:nil views:myDictionary];

我还没有测试过这个(我仍然需要编写很多代码来循环数据和所有这些),但它应该可以工作。正如我所说,我看到的所有示例都对尺寸进行了硬编码,所以我想我会发布这个,以防其他人来寻找如何做到这一点,或者以防我稍后忘记=)。

【讨论】:

以上是关于具有自动布局的 UITableView 中的动态列的主要内容,如果未能解决你的问题,请参考以下文章

具有自动布局的 UITableView 中的动态单元格高度

使用自动布局的 UITableView 中的动态 UITextView 高度?

自动布局动态大小 uitableview 单元格的最佳方法是啥

在 UITableView 中使用自动布局进行动态单元格布局和可变行高

在 UITableView 中使用自动布局进行动态单元格布局和可变行高

UITableViewHeaderFooterView 不支持笔尖中的自动布局约束