设计 UIView 使其可以根据内容高度动态更改其高度
Design UIView so that it can dynamically change its height based on the content height
在 XIB
文件中,我有一个 CustomView
与同名的 class 相关。
查看内容很简单。
有一个垂直 stackview,在 stackview 里面有两个 labels。 stackview 与包含它的视图垂直对齐:
第一个标签(标题)包含静态文本(总是几个字符)。
第二个标签(副标题)可以有可变长度的文本。
我将此 CustomView
与其他类似视图一起添加为 Content View
的子视图,因为它是一个“行”。
for i in 0...aViews.count {
var v = CustomView(frame: CGRect(x: 0, y: _y, width: 320, height: 100))
v.labelText = "my long label text ..."
contentView.addSubview(v)
// ...
}
你可以想象,标题标签应该有一个固定的位置(顶部和左侧),即不能有一个行标题从10点开始并且另一个在 14 岁。
我必须承认,我天真地认为标签的位置会自动管理,因为我垂直对齐了 stackview。我错了,我没有发现任何问题,直到他们告诉我第二个标签,副标题,可以包含不止一行。
我直接在storyboard
中给标签加了行,结果发现:
stackview 的容器不会根据其内容的 height
更改其 height
;
“固定”元素的位置可能垂直居中但不是固定的;
我需要的是:
- 标签应该“分组”并垂直对齐:从第一个标签的顶部到容器的上边框以及从第二个标签的底部应该有相同数量的space到底部边框;
- 当第二个标签必须显示多行时,容器视图应相应地更改其高度;
这可能吗?我应该如何设计我的视图?
我认为您混合了外部视图的绝对定位(即手动设置框架)和对其内部组件使用自动布局约束,并且错误地期望动态自动布局部分以某种方式 "reach all the way up" 到外部视图。对于自动布局,您需要一直使用自动布局,包括 CustomViews
在 contentView
.
中的定位方式
如果出于某种原因你不想为此使用 TableView 或 CollectionView,你也可以,例如,尝试将你的 CustomView
s 作为排列的子视图添加到具有 top/bottom/leading/trailing 约束到 contentView
,然后将 CustomView
的 "Align Center Y" 约束替换为 "Align Top" 和 "Align Bottom" 约束,以实际允许标签从 "push"里面如果他们需要更多的垂直 space.
编辑 这里有一个快速草图来说明该设置:
编辑 2 这里有几个屏幕截图可以进一步说明。使用这样的基本布局:
运行时结果如下所示:
请注意,UIStackViews 在本例中使用 "Equal Spacing" Distribution。如果您想以编程方式创建和添加 CustomView
,请使用 StackView 的 func addArrangedSubview(_ view: UIView)
。
祝你好运!
好的 - 看看你的项目,你离得不远了......只是几个关键项目。
在您的 CustomView.xib 中,您在 Fixed Label
和 Date Label
之间没有任何限制。结果是 Date Label
从视图底部向上 增长,没有任何东西可以阻止它。
同样在您的 CustomView.xib 中,您将 Fixed Label
限制在后缘...我假设您希望它与 Date Label
[ 左对齐=23=]
创建 CustomView 时,您将高度限制设置为 100 -- 这违背了允许内容确定大小的目的。
在 CustomView class 中,您已将 contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
注释掉。那条线应该在那里。
在您的视图控制器中,您向 contentView
添加了低优先级的高度限制。最好的选择是将其设为占位符约束(双击约束,然后 select 占位符复选框)。这样,约束在 运行 时被移除,但在设计期间存在(故事板不会抱怨)。
您正在做一些其他不必要的事情 - 可能您正在尝试不同的东西来让它工作。
视图设置(添加您的视图)最好在 viewDidLoad()
中完成 -- 绝对不会 在 viewDidLayoutSubviews()
[=23 中完成=]
我猜想,在您的 CustomView 中,您 可能 想要限制 Date Label
前导和拖尾,允许它根据设备宽度水平拉伸...但我将其保留在 200。
如果您能遵循该信息,您应该能够解决问题。但是,我把这个项目作为一个 GitHub 存储库给你,这样你就可以得到它的 "working" 状态,这样你就可以看到变化。
这是回购的 link:https://github.com/DonMag/ATester2
结果如下:
向上滚动一点:
在 XIB
文件中,我有一个 CustomView
与同名的 class 相关。
查看内容很简单。
有一个垂直 stackview,在 stackview 里面有两个 labels。 stackview 与包含它的视图垂直对齐:
第一个标签(标题)包含静态文本(总是几个字符)。 第二个标签(副标题)可以有可变长度的文本。
我将此 CustomView
与其他类似视图一起添加为 Content View
的子视图,因为它是一个“行”。
for i in 0...aViews.count {
var v = CustomView(frame: CGRect(x: 0, y: _y, width: 320, height: 100))
v.labelText = "my long label text ..."
contentView.addSubview(v)
// ...
}
你可以想象,标题标签应该有一个固定的位置(顶部和左侧),即不能有一个行标题从10点开始并且另一个在 14 岁。
我必须承认,我天真地认为标签的位置会自动管理,因为我垂直对齐了 stackview。我错了,我没有发现任何问题,直到他们告诉我第二个标签,副标题,可以包含不止一行。
我直接在storyboard
中给标签加了行,结果发现:
stackview 的容器不会根据其内容的
height
更改其height
;“固定”元素的位置可能垂直居中但不是固定的;
我需要的是:
- 标签应该“分组”并垂直对齐:从第一个标签的顶部到容器的上边框以及从第二个标签的底部应该有相同数量的space到底部边框;
- 当第二个标签必须显示多行时,容器视图应相应地更改其高度;
这可能吗?我应该如何设计我的视图?
我认为您混合了外部视图的绝对定位(即手动设置框架)和对其内部组件使用自动布局约束,并且错误地期望动态自动布局部分以某种方式 "reach all the way up" 到外部视图。对于自动布局,您需要一直使用自动布局,包括 CustomViews
在 contentView
.
如果出于某种原因你不想为此使用 TableView 或 CollectionView,你也可以,例如,尝试将你的 CustomView
s 作为排列的子视图添加到具有 top/bottom/leading/trailing 约束到 contentView
,然后将 CustomView
的 "Align Center Y" 约束替换为 "Align Top" 和 "Align Bottom" 约束,以实际允许标签从 "push"里面如果他们需要更多的垂直 space.
编辑 这里有一个快速草图来说明该设置:
编辑 2 这里有几个屏幕截图可以进一步说明。使用这样的基本布局:
运行时结果如下所示:
请注意,UIStackViews 在本例中使用 "Equal Spacing" Distribution。如果您想以编程方式创建和添加 CustomView
,请使用 StackView 的 func addArrangedSubview(_ view: UIView)
。
祝你好运!
好的 - 看看你的项目,你离得不远了......只是几个关键项目。
在您的 CustomView.xib 中,您在
Fixed Label
和Date Label
之间没有任何限制。结果是Date Label
从视图底部向上 增长,没有任何东西可以阻止它。同样在您的 CustomView.xib 中,您将
Fixed Label
限制在后缘...我假设您希望它与Date Label
[ 左对齐=23=]创建 CustomView 时,您将高度限制设置为 100 -- 这违背了允许内容确定大小的目的。
在 CustomView class 中,您已将
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
注释掉。那条线应该在那里。在您的视图控制器中,您向
contentView
添加了低优先级的高度限制。最好的选择是将其设为占位符约束(双击约束,然后 select 占位符复选框)。这样,约束在 运行 时被移除,但在设计期间存在(故事板不会抱怨)。您正在做一些其他不必要的事情 - 可能您正在尝试不同的东西来让它工作。
视图设置(添加您的视图)最好在
viewDidLoad()
中完成 -- 绝对不会 在viewDidLayoutSubviews()
[=23 中完成=]我猜想,在您的 CustomView 中,您 可能 想要限制
Date Label
前导和拖尾,允许它根据设备宽度水平拉伸...但我将其保留在 200。
如果您能遵循该信息,您应该能够解决问题。但是,我把这个项目作为一个 GitHub 存储库给你,这样你就可以得到它的 "working" 状态,这样你就可以看到变化。
这是回购的 link:https://github.com/DonMag/ATester2
结果如下:
向上滚动一点: