iOS AutoLayout多

下面的问题是这一类的延续:

iOS:自动布局中的多行UILabel

主要思想是每个视图都应该声明它是“首选”(内在)大小,以便AutoLayout可以知道如何正确显示它。 UILabel仅仅是一种情况的例子,在这种情况下,视图本身并不知道它需要显示的尺寸。 这取决于提供的宽度。

正如mwhuss指出的那样,setPreferredMaxLayoutWidth完成了将标签跨越多行的技巧。 但这不是这里的主要问题。 问题是我何时以及何时将这个宽度值作为setPreferredMaxLayoutWidth的参数发送。

我设法做出一些看起来合法的东西,所以如果我有任何问题,请纠正我,如果你知道更好的方法,请告诉我。

在UIView的

-(CGSize) intrinsicContentSize

根据self.frame.width为我的UILabels设置了PreferredMaxLayoutWidth。

UIViewController的

-(void) viewDidLayoutSubviews

是我知道的第一个回调方法,其中主视图的子视图是用屏幕上居住的确切帧指定的。 然后,从那个方法中,我对我的子视图进行操作,使它们的内在大小无效,以便UILabel根据指定给它们的宽度分成多行。


看起来令人讨厌的是,如果你有一些约束条件明确地为你定义了这个宽度,那么UILabel不会默认它的宽度作为首选的最大布局宽度。

几乎在每种情况下,我都使用Autolayout下的标签,一旦我的布局的其余部分执行完毕,首选的最大布局宽度就是标签的实际宽度。

所以,为了自动发生这种情况,我使用了一个UILabel子类,它覆盖了setBounds: 在这里,调用超级实现,然后, 如果不是这种情况 ,请将首选最大布局宽度设置为边界大小宽度。

重点非常重要 - 设置首选最大布局会导致执行另一个布局传递,因此最终可能会出现无限循环。


在高级自动布局工具箱的“多行文本的内部内容大小”部分中,有关objc.io的这个问题的答案。 以下是相关信息:

对于多行文本,UILabel和NSTextField的内在内容大小不明确。 文本的高度取决于线条的宽度,这在解决约束时尚未确定。 为了解决这个问题,两个类都有一个名为preferredMaxLayoutWidth的新属性,它指定了用于计算内在内容大小的最大行宽。

由于我们通常不会提前知道这个值,所以我们需要采取两步走的方法才能做到这一点。 首先,我们让自动布局执行其工作,然后使用布局过程中的结果帧再次更新首选最大宽度和触发布局。

他们在视图控制器中使用的代码:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [self.view layoutIfNeeded];
}

看看他们的帖子,还有更多关于为什么需要两次布局的信息。


更新

我的原始答案似乎很有帮助,所以我没有在下面留下它,但是,在我自己的项目中,我发现了一个更可靠的解决方案,可以解决iOS 7和iOS 8中的错误。https://github.com/nicksnyder/ios胰岛β细胞布局

原始答案

这是一个适用于iOS 7和iOS 8的完整解决方案

目标C

@implementation AutoLabel

- (void)setBounds:(CGRect)bounds {
  if (bounds.size.width != self.bounds.size.width) {
    [self setNeedsUpdateConstraints];
  }
  [super setBounds:bounds];
}

- (void)updateConstraints {
  if (self.preferredMaxLayoutWidth != self.bounds.size.width) {
    self.preferredMaxLayoutWidth = self.bounds.size.width;
  }
  [super updateConstraints];
}

@end

迅速

import Foundation

class EPKAutoLabel: UILabel {

    override var bounds: CGRect {
        didSet {
            if (bounds.size.width != oldValue.size.width) {
                self.setNeedsUpdateConstraints();
            }
        }
    }

    override func updateConstraints() {
        if(self.preferredMaxLayoutWidth != self.bounds.size.width) {
            self.preferredMaxLayoutWidth = self.bounds.size.width
        }
        super.updateConstraints()
    }
}
链接地址: http://www.djcxy.com/p/28219.html

上一篇: iOS AutoLayout multi

下一篇: UIButton with background image: title text randomly does not appear