正确的方法(在autolayout中)调整superview和重新布局子视图的大小?

时间:2014-04-24 18:48:34

标签: ios xcode5 autolayout

我正试图弄清楚自动布局问题。我有一个小的自定义视图,它本身有一个imageView和几个标签。图像从服务器获取并包含一些元数据,以帮助应用程序确定文本的放置位置。现在,我只需要限制标签的宽度(触发自动换行),以避免将文字放在背景中的徽标顶部。

为了使这更容易,我想我可以为这两个标签创建一个包含视图。这样,我可以调整容器的大小,(我认为)子视图也会效仿。

Screenshot from Xcode

我很确定我已经正确设置了约束,因为一切正常,直到我开始摆弄框架:

Image before fiddling

从服务器获取图像时,我按如下方式调整帧的大小:

CGRect frame = self.labelContainerView.frame;
frame.size.width = my_limited_width;
self.labelContainerView.frame = frame;

我可以看到容器本身已经调整大小,但它的子视图没有:

Resized container with un-resized child views

为了尝试触发布局,我已经完成了:

[self.labelContainerView setNeedsLayout];
[self.labelContainerView layoutIfNeeded];

...但最终只是从.xib恢复原始约束。这是一个方便的功能,而且......它是我可能需要的......但不是我需要的。

我看过那些暗示调整帧大小的帖子在这里做错了;你应该掌握适当的约束并改为使用它。我试过了:

self.rightMarginConstraint.constant = 150;

......它几乎可以运作:

Adjusted constraint on right edge of superview

但是在这种情况下,第一个(更大的)标签永远不会超过两行,即使它的高度约束被设置为< =非常大的东西。布局系统不会重新计算标签需要多少行。

显然我对于视图,框架和自动布局一起工作以便能够自己看到解决方案的方式不够了解,这就是我在这里问的原因。解决这个问题的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

正如@MatíasR在评论中指出的那样,正确的方法是操纵约束而不是直接设置框架。

我将此提交给Apple开发者技术支持(DTS)并收到了我的问题第二部分的答案。发生布局时,标签需要更新其preferredMaxLayoutWidth:

- (void)viewDidLayoutSubviews
{
    self.titleLabel.preferredMaxLayoutWidth = self.titleLabel.bounds.size.width;
    self.subtitleLabel.preferredMaxLayoutWidth = self.subtitleLabel.bounds.size.width;
    [super viewDidLayoutSubviews];
}

我仍然需要强制使用新布局,但这很简单:

self.rightMarginConstraint.constant = 150;
[self.labelContainerView setNeedsLayout];
[self.labelContainerView layoutIfNeeded];

感谢@MatíasR帮助消除变量。一旦我知道正确的方法,我就能够向DTS提交一个非常具体的示例代码块。