下面的问题是这个问题的延续:
iOS:自动布局中的多行 UI标签
主要思想是,每个视图都应该声明其“首选”(固有)大小,以便AutoLayout可以知道如何正确显示它。UILabel只是视图本身无法知道显示所需的大小的情况的一个例子。这取决于提供的宽度。
正如mwhuss所指出的,setPreferredMaxLayoutWidth实现了使标签跨越多行的技巧。但这不是这里的主要问题。问题是,我在何时何地获得这个宽度值,作为参数发送给setPreferredMaxLayoutWidth。
我设法做了一些看起来合法的东西,所以如果我在任何方面错了,请纠正我,如果你知道更好的方法,请告诉我。
在UIView中
-(CGSize) intrinsicContentSize
我根据self.frame.width.为我的UILabels设置PreferredMaxLayoutWidth
UIViewController的
-(void) viewDidLayoutSubviews
是我所知道的第一个回调方法,其中主视图的子视图被指定为它们在屏幕上的确切框架。然后,从该方法内部,我对我的子视图进行操作,使它们的内在大小无效,以便根据指定给它们的宽度将UILabels分成多行。
更新
我最初的答案似乎很有帮助,所以我在下面没有触及它,但是,在我自己的项目中,我找到了一个更可靠的解决方案,可以解决iOS7和iOS8中的错误。https://github.com/nicksnyder/ios-cell-layout
原答案
这是一个完整的解决方案,适用于我在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()
}
}
UILabel 不会默认其宽度作为首选最大布局宽度,这似乎很烦人,如果您有明确定义该宽度的约束。
几乎在我在“自动布局”下使用标签的每一种情况下,在执行完布局的其余部分后,首选的最大布局宽度都是标签的实际宽度。
因此,为了自动实现这一点,我使用了一个UILabel子类,它覆盖了setBound:
。在这里,调用超级实现,然后,如果不是这样,将首选的最大布局宽度设置为边界大小宽度。
重点很重要-设置首选最大布局会导致执行另一个布局过程,因此可能会导致无限循环。
在高级自动布局工具箱的“多行文本的固有内容大小”部分的objc.io上有这个问题的答案。以下是相关信息:
对于多行文本,UILabel和NSTextField的固有内容大小不明确。文本的高度取决于线条的宽度,这在求解约束时尚待确定。为了解决这个问题,这两个类都有一个名为preferredMaxLayoutWidth的新属性,该属性指定用于计算固有内容大小的最大线宽。
由于我们通常事先不知道这个值,我们需要采取两步的方法来实现这一点。首先我们让自动布局完成它的工作,然后我们在布局过程中使用生成的帧来更新首选的最大宽度并再次触发布局。
它们给出的用于视图控制器的代码:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[self.view layoutIfNeeded];
}
看看他们的帖子,有更多关于为什么需要做两次布局的信息。
我在尝试用自动布局实现一些非常基本的布局行为时遇到了困难。我的视图控制器在IB中看起来是这样的: 最上面的标签是标题标签,不知道会有多少行。我需要标题标签显示所有的文字行。我还需要另外两个标签和小的图像,以布局的权利下面的标题,但它恰巧是高的。我设置了标签和小图像之间的垂直间距约束,以及标题标签和它的超级视图之间的顶部间距约束和小图像和它的超级视图之间的底部间距约束。白色UIView没有高度限制,
Material Design 中的响应式布局适用于任何尺寸的屏幕。自适应 UI 手册包含:保证布局一致性的灵活网格、内容如何在不同屏幕上重绘的断点细节以及关于一个应用如何从小的屏幕缩放到超大屏幕的描述。 断点 为了最优的用户体验,Material 用户界面应该适应如下断点宽度的布局:480、600、840、960、1280、1440 以及 1600 dp。 1.布局中的总结和细节显示内容 600
我有一个带有两个标签和一个小图像的表视图单元格。如果标签文本很短,则所有文本都放在一行中,如下所示: 但是,如果标签文本越来越长,图像和第二个标签应该移动到第二行: 我该如何使用自动布局来做到这一点? 第一个标签很简单 - 只需为左侧和顶部添加约束即可。标签始终只有一行,如果文本太长,标签会在中间被截断。 图像必须始终水平位于第二个标签(默认空间)的前面,并且两个标签都垂直居中。图像大小应与标签的
我遇到了自动布局的问题,似乎无法找到应该很容易实现的答案。 我有以下视图层次结构: 标签上的前导/尾随限制使它们在更薄的设备上更高(iPhone 4s vs iPhone 6)。 为了让UIScrollview正常工作,我需要在UIScrollView内部设置UIView的高度约束,以避免出现“不明确的高度”警告。 但在iPhone 4s上运行时,UIView不够高,无法容纳它的子视图。 到目前为
你可能用过UIViewAutoresizingMask类型的一些常量,应用于当父视图改变尺寸的时候,相应UIView的frame也跟着更新的场景(通常用于横竖屏切换)。 在iOS6中,苹果介绍了自动排版机制,它和自动调整不同,并且更加复杂。 在Mac OS平台,CALayer有一个叫做layoutManager的属性可以通过CALayoutManager协议和CAConst
我正在尝试学习自动布局,当这件事发生时,我最终认为我已经掌握了它。我正在玩原型细胞和标签。我正在尝试 < li >标题,< code>titleLbl -图片中的蓝色方框 < li >货币,< code>moneyLbl -图片中的绿色方框 < li >副标题/描述,< code >副标题< code> -图片中的红色方框 到目前为止,我有这个: 我想实现的是: 绿色框应始终完全显示在1行 绿色框