自动布局动态.xib视图高度

17

我没有找到太多关于在各自的.xib文件中使用AutoLayout的内容...

我有一个独立的.xib文件,其中包含3个视图 - 一个头视图(包含两个标签),一个输入视图和一个页脚(包含两个按钮)。 它看起来像这样:

enter image description here

头视图中的标签具有应影响头视图垂直大小以及整个视图大小的约束条件。 子标题是带有0行的标签,这意味着它是多行的和动态的。 其他所有内容都具有设置高度,具有水平约束到superview和顶部约束到兄弟姐妹(或header view情况下的superview)。

我遇到的问题是,当我在代码中加载此.xib文件进行显示时,高度始终是静态的,基于Xcode检查器中定义的内容。 是否可以根据宽度使整个视图的高度动态变化(影响动态标签高度,从而影响其余视图)?

例如 - 如果我从.xib加载此视图并将其宽度设置为300,则如何调整其高度以适应动态标签的新高度? 我需要使用intrinsicContentSize方法来定义此大小吗?

3个回答

18

经过大量实验和阅读,我找到了答案。当在某些构造函数(在我的情况下是类级别的便捷方法)中加载.xib时,必须确保调用[view setTranslatesAutoresizingMaskIntoConstraints:NO];例如,我已经执行以下操作:

+ (InputView *)inputViewWithHeader:(NSString *)header subHeader:(NSString *)subHeader inputValidation:(ValidationBlock)validation
{
    InputView *inputView = [[[NSBundle mainBundle] loadNibNamed:@"InputView" owner:self options:nil] lastObject];
    if ([inputView isKindOfClass:[InputView class]]) {
        [inputView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [inputView configureWithHeader:header subHeader:subHeader inputValidation:validation];
        [inputView layoutIfNeeded];
        [inputView invalidateIntrinsicContentSize];
        return inputView;
    }
    return nil;
}

接下来,需要覆盖重写 layoutSubviewsintrinsicContentSize 方法。覆盖重写 layoutSubviews 允许我设置标签的 preferredMaxLayoutWidth,而覆盖重写 intrinsicContentSize 方法允许我根据约束和子视图计算大小! 这是我实现它们的代码:

- (void)layoutSubviews {
    [super layoutSubviews];
    self.subHeaderLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
    [super layoutSubviews];
}

- (CGSize)intrinsicContentSize {
    CGFloat height = self.headerView.bounds.size.height;
    height += self.headerInputSpacer.constant;
    height += self.inputField.bounds.size.height;
    height += self.inputButtonSpacer.constant;
    height += self.buttonView.bounds.size.height;
    CGSize size = CGSizeMake([UIScreen mainScreen].bounds.size.width - 20, height);
    return size;
}

我确信有改进这个代码的方法,或者更好的方式实现它,但是至少现在它大小正确!对于不应该具有用户定义框架的视图非常有用。


为什么您要调用 layoutSubviews 两次? - Iulian Onofrei
我尝试了一下,但对我没用。你能把一个演示粘贴到GitHub上吗?非常感谢~ - Neko
@Neko,请尝试使用我下面列出的解决方案。 - JackyW

3
这是我的做法(Swift版本):
将所有内容嵌入视图中。你的xib层次结构应该是:
- 你的xib - View - Everything else,例如你的标签、按钮等
View的约束应该限制到superview(即你的xib)的顶部、前导和尾随,并且在“everything else”中,应该有一个对象的底部约束到superview(View)。
在你的代码中:
加载nib
nib.frame.size.width = 80 // Set your desired width here

nib.label.text = "hello world" // Set your dynamic text here

nib.layoutIfNeeded() // This will calculate and set the heights accordingly

nib.frame.size.height = nib.view.frame.height + 16 // 16 is the total of top gap and bottom gap of auto layout

对于我的情况,我将这个xib加载到集合视图的单元格中,该xib的高度需要动态调整,并且宽度需要跟随单元格的宽度。最后,上面的代码块位于我的集合视图的cellForItemAt方法内。
希望这有所帮助。

1
layoutIfNeeded() 挽救了局面。 - Kampai

0

很遗憾,我不确定我缺少了什么。上述方法对我来说无法获取xib单元格的高度或让layoutifneeded()、UITableView.automaticDimension进行高度计算。我已经搜索和尝试了3到4个晚上,但没有答案。 这里或另一篇帖子的一些答案确实给了我解决方法的提示。这是一个愚蠢的方法,但它有效。只需将所有单元格添加到数组中。然后在xib故事板中设置每个高度约束的输出口。最后,在heightForRowAt方法中将它们相加。如果您不熟悉这些API,则非常简单。

Swift 4.2

CustomCell.Swift

@IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
@IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
@IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!

@IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
@IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!

MyTableViewVC.Swift

.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell

.
.
myCustomCells.append(cell)
return cell

}


override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

   let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant +  myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant

  return totalHeight + 40 //some magic number


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接