ChatGPT解决这个技术问题 Extra ChatGPT

iOS:自动布局中的多行 UILabel

我在尝试使用自动布局实现一些非常基本的布局行为时遇到了麻烦。我的视图控制器在 IB 中看起来像这样:

https://i.stack.imgur.com/pg6fl.png

最上面的标签是标题标签,不知道会有多少行。我需要标题标签来显示所有文本行。我还需要将另外两个标签和小图像放在标题的正下方,不管它有多高。我已经设置了标签和小图像之间的垂直间距约束,以及标题标签与其父视图之间的顶部间距约束以及小图像与其父视图之间的底部间距约束。白色的 UIView 没有高度限制,因此它应该垂直拉伸以包含其子视图。我已将标题标签的行数设置为 0。

如何让标题标签调整大小以适应字符串所需的行数?我的理解是我不能使用 setFrame 方法,因为我使用的是自动布局。而且我必须使用自动布局,因为我需要那些其他视图保持在标题标签下方(因此有约束)。

我怎样才能做到这一点?

我也在与类似的问题作斗争。但我仍在努力让顶部标签动态调整其高度以适应内容。你是如何做到这一点的?
请考虑将@mwhuss 的答案标记为已接受的答案。
你达到了要求的结果吗?
检查这个,你不需要添加单行代码stackoverflow.com/a/36862795/4910767

B
Bruno Bieri

UILabel 上使用 -setPreferredMaxLayoutWidth,其余部分应由自动布局处理。

[label setPreferredMaxLayoutWidth:200.0];

请参阅 UILabel documentation on preferredMaxLayoutWidth

更新:

只需将storyboard中的height约束设置为Greater than or equal to,无需设置PreferredMaxLayoutWidth。


不错,无论如何要在界面生成器中执行此操作?
还要将 IB 中的高度约束设置为“大于或等于”。
提醒:请记得设置 numberOfLines 属性。
是的,使用任何你想要的最大宽度。
请参阅 stackoverflow.com/a/29180323/1529675 了解如何确定 preferredMaxLayoutWidth,并参阅 devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html 了解简短但内容丰富的文章,并附上动画 GIF(不是我的文章,我通过 Google 找到的)
m
mfaani

将标签集的行数扩展为 0,更重要的是,将自动布局集高度设置为 >= x。自动布局将完成其余的工作。您还可以包含基于先前元素的其他元素以正确定位。

https://i.stack.imgur.com/wzfxk.png


如果此方法对您不起作用,请参阅 Cory Imdieke 关于确保后续视图不会禁止自动布局调整(可能)多行视图大小的答案。
这是在表格视图单元格中对我有用的唯一答案。也适用于固定数量的行(而不是 0/无限)
这对我来说不适用于明确的首选最大宽度设置,因此请确保在使用此技术时在 IB 中将其设置为自动。干杯
设置自动最大宽度仅在 iOS8 中可用。据我了解,它还会自动调整高度,根据我的经验,您无需设置高度约束即可使其工作。这对我使用明确的宽度有用。
这对我不起作用。我相信 stackoverflow.com/a/13032251/1529675 是正确答案。
A
Anton Matosov

来源:http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

多行文本的内在内容大小

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

由于我们通常事先不知道这个值,因此我们需要采取两步的方法来解决这个问题。首先我们让 Auto Layout 完成它的工作,然后我们在布局过程中使用生成的框架来更新首选的最大宽度并再次触发布局。

- (void)layoutSubviews
{
    [super layoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [super layoutSubviews];
}

第一次调用 [super layoutSubviews] 是标签获取其框架集所必需的,而第二次调用是在更改后更新布局所必需的。如果我们省略第二次调用,我们会得到一个 NSInternalInconsistencyException 错误,因为我们在布局过程中进行了更改,需要更新约束,但我们没有再次触发布局。

我们也可以在标签子类本身中执行此操作:

@implementation MyLabel
- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

在这种情况下,我们不需要先调用 [super layoutSubviews],因为当 layoutSubviews 被调用时,我们已经在标签本身上有了一个框架。

为了从视图控制器级别进行此调整,我们挂钩到 viewDidLayoutSubviews。此时,第一个 Auto Layout pass 的框架已经设置好了,我们可以使用它们来设置首选的最大宽度。

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

最后,确保标签上没有明确的高度约束,其优先级高于标签的内容压缩阻力优先级。否则它将胜过计算的内容高度。确保检查所有可能影响标签高度的约束。


谢谢谢谢谢谢,不仅是代码,更重要的是解释和示例,不仅在子类中,而且在视图控制器中。
我在我的视图控制器中尝试这样做,并且在 viewWillAppear 和 viewDidAppear 之后调用 viewDidLayoutSubviews。在 viewDidAppear 之后,当标签正确调整大小时会闪烁。有没有办法避免这种情况?有没有办法在用户看到任何东西之前完成调整大小?就我而言,我的多行标签位于 tableHeaderView 中,因此我还使用此示例(stackoverflow.com/questions/20982558/…)根据标签调整标题视图的高度
@djibouti33 您能否提供最低限度的示例代码(例如 github repo 的格式),以便我可以轻松检查您的问题?
谢谢@Anton。我们的设计已经从 UITableView 切换到 UICollectionView,幸运的是我没有看到这种行为。如果我可以在我的 git 历史中创建一个小型示例项目,我会告诉你的。
自从我开始在 iOS 9 sim 上运行以来对我来说是一个问题,但是当我在 iOS 8 上进行测试时,问题就开始了。我需要手动设置最大宽度。
C
Cory Imdieke

我只是在与这个确切的场景作斗争,但是还有很多视图需要根据需要调整大小并向下移动。这让我发疯,但我终于想通了。

这是关键:Interface Builder 喜欢在您添加和移动视图时加入额外的约束,而您可能不会注意到。在我的例子中,我有一个视图在中途有一个额外的约束,指定它和它的父视图之间的大小,基本上将它固定到那个点。这意味着它上面的任何东西都不能调整得更大,因为它会违反这个约束。

判断是否是这种情况的一种简单方法是尝试手动调整标签大小。 IB会让你成长吗?如果是这样,下面的标签是否按照您的预期移动?在调整大小以查看约束将如何移动视图之前,请确保已检查这两项:

https://i.stack.imgur.com/ot9G6.png

如果视图被卡住,请遵循其下方的视图,并确保其中一个视图没有顶部空间来进行超级视图约束。然后只需确保标签的行数选项设置为 0,它应该会处理其余部分。


是的,在玩了很多之后,我能够得到我想要的效果。你只需要非常仔细地考虑你想要的约束。 IB 不断地施加你意想不到的限制,这于事无补。
C
Chris

我发现您需要以下内容:

顶部约束

前导约束(例如左侧)

尾随约束(例如右侧)

设置内容拥抱优先级,水平到低,如果文本很短,它将填充给定的空间。

设置内容压缩阻力,水平到低,所以它会换行而不是尝试变宽。

将行数设置为 0。

将换行模式设置为自动换行。


这应该在 xcode9 中工作。我不必对标签高度约束做任何事情(我没有):它只是在标签受到约束(尾随、前导、顶部和底部)后开箱即用。 uikit 完成剩下的工作
拥抱优先的内容是我的问题。感谢您让我了解该特性以及抗压性。你帮我解决了一个长达数小时的问题。
T
Tanguy G.

在有关该主题的许多主题中找到的不同解决方案都没有完美地适用于我的案例(动态表格视图单元格中的 x 动态多行标签)。

我找到了一种方法:

在标签上设置约束并将其多行属性设置为 0 后,创建 UILabel 的子类;我叫我的 AutoLayoutLabel :

@implementation AutoLayoutLabel

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

@end

A
Alvin George

我有一个 UITableViewCell ,它有一个文本换行标签。我按如下方式进行文本换行。

1) 设置 UILabel 约束如下。

https://i.stack.imgur.com/ODSQP.png

2) 设置编号。行数为 0。

3) 为 UITableViewCell 添加了 UILabel 高度约束。

@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!

4) 在 UITableViewCell 上:

priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5

M
Mureinik

一种方法...随着文本长度的增加,尝试使用更改(减小)标签文本的字体大小

Label.adjustsFontSizeToFitWidth = YES;

我希望视图控制器的不同实例具有一致的外观,所以我不想更改字体大小。