在 viewWillAppear 中设置约束
Setting Constraints in viewWillAppear
我在viewcontroller
中间有一个uiview
。这个uiview
.
上面(A)下面有一个uilabel
我想以编程方式更改此 uiview
的底部约束,以便随着屏幕尺寸的变化,uiview
上方和下方的距离彼此相等。所以计算顶部 uiview
到 uilabel
底部的距离 (A) 和底部 uiview
到 uilabel
顶部的距离 (B),除以 2 然后设置相应的底部约束常数。
我已经完成了计算,但它似乎只有在我将它放在 viewDidAppear
中时才有效,并且我需要在用户能够看到对象之前将约束和视图放在正确的位置。这可以在 viewWillAppear
中完成吗?感觉所有元素直到 viewDidAppear
才设置好让我正确计算..我相信这与 autolayout
的生命周期有关,在计算之前未完成..
let topDistance = view.frame.minY - ALabel.frame.maxY
let bottomDistance = BLabel.frame.minY - view.frame.maxY
let total = topDistance + bottomDistance
bottomConstraint.constant = total / 2
下面是所需结果的 before/after 示例,其中紫色 uiview
对底部橙色 uilabel
具有底部约束。例如,当屏幕尺寸增加时,我希望底部约束与紫色 uiview
和顶部橙色 uilabel
之间的距离具有相同的常数。顶部 uilabel
对顶部有顶部约束,底部 uilabel
对底部有底部约束。
更新约束后写入layoutIfNeeded
。
let topDistance = view.frame.minY - ALabel.frame.maxY
let bottomDistance = BLabel.frame.minY - view.frame.maxY
let total = topDistance + bottomDistance
bottomConstraint.constant = total / 2
self.view.layoutIfNeeded()
当您使用 View 时,用户已经看到 VeiwController,
请改用 viewDidLoad ,您不能使用 viewWillAppear ,因为尚未加载视图。
用于:
override func viewDidLoad() {
super.viewDidLoad()
}
你可以试试打电话给
self.view.layoutIfNeeded()
当我想以编程方式设置约束时,我通常会这样进行:
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
v.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
v.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true
v.heightAnchor.constraint(equalToConstant: 100).isActive = true
v.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor).isActive = true
您可以为此使用 Dispatch Queue:
DispatchQueue.main.async {
let topDistance = view.frame.minY - ALabel.frame.maxY
let bottomDistance = BLabel.frame.minY - view.frame.maxY
let total = topDistance + bottomDistance
bottomConstraint.constant = total / 2
self.view.layoutIfNeeded()
}
尝试回答您的问题:
你是对的,自动布局在 viewDidLoad()
甚至 viewWillAppear()
中都没有完成它的工作。通常,当您需要进行这样的布局调整时,您希望在 viewDidLayoutSubviews()
中进行。来自 Apple 的文档:
viewDidLayoutSubviews
When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method.
但是,如果我理解您实际想要做什么...
通过使用 UIStackView
,您可以避免使用 任何 代码。
将您的标签、视图、按钮等嵌入垂直 UIStackView
。将属性设置为:
Alignment: Fill (or Leading or Center as suits your layout)
Distribution: Equal Spacing
Spacing: 0
将堆栈视图的顶部约束到视图的顶部(加上任何所需的填充)并将底部约束到视图的底部(加上任何所需的填充)。
iPhone SE 大小的结果:
iPhone 8 尺寸的结果:
iPhone XS 码的结果:
还有,这里是 iPhone 8,还有一些不同高度的附加元素:
如您所见,元素之间的垂直间距相等,并且全部由堆栈视图处理。
我在viewcontroller
中间有一个uiview
。这个uiview
.
uilabel
我想以编程方式更改此 uiview
的底部约束,以便随着屏幕尺寸的变化,uiview
上方和下方的距离彼此相等。所以计算顶部 uiview
到 uilabel
底部的距离 (A) 和底部 uiview
到 uilabel
顶部的距离 (B),除以 2 然后设置相应的底部约束常数。
我已经完成了计算,但它似乎只有在我将它放在 viewDidAppear
中时才有效,并且我需要在用户能够看到对象之前将约束和视图放在正确的位置。这可以在 viewWillAppear
中完成吗?感觉所有元素直到 viewDidAppear
才设置好让我正确计算..我相信这与 autolayout
的生命周期有关,在计算之前未完成..
let topDistance = view.frame.minY - ALabel.frame.maxY
let bottomDistance = BLabel.frame.minY - view.frame.maxY
let total = topDistance + bottomDistance
bottomConstraint.constant = total / 2
下面是所需结果的 before/after 示例,其中紫色 uiview
对底部橙色 uilabel
具有底部约束。例如,当屏幕尺寸增加时,我希望底部约束与紫色 uiview
和顶部橙色 uilabel
之间的距离具有相同的常数。顶部 uilabel
对顶部有顶部约束,底部 uilabel
对底部有底部约束。
更新约束后写入layoutIfNeeded
。
let topDistance = view.frame.minY - ALabel.frame.maxY
let bottomDistance = BLabel.frame.minY - view.frame.maxY
let total = topDistance + bottomDistance
bottomConstraint.constant = total / 2
self.view.layoutIfNeeded()
当您使用 View 时,用户已经看到 VeiwController, 请改用 viewDidLoad ,您不能使用 viewWillAppear ,因为尚未加载视图。
用于:
override func viewDidLoad() {
super.viewDidLoad()
}
你可以试试打电话给
self.view.layoutIfNeeded()
当我想以编程方式设置约束时,我通常会这样进行:
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
v.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
v.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20).isActive = true
v.heightAnchor.constraint(equalToConstant: 100).isActive = true
v.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor).isActive = true
您可以为此使用 Dispatch Queue:
DispatchQueue.main.async {
let topDistance = view.frame.minY - ALabel.frame.maxY
let bottomDistance = BLabel.frame.minY - view.frame.maxY
let total = topDistance + bottomDistance
bottomConstraint.constant = total / 2
self.view.layoutIfNeeded()
}
尝试回答您的问题:
你是对的,自动布局在 viewDidLoad()
甚至 viewWillAppear()
中都没有完成它的工作。通常,当您需要进行这样的布局调整时,您希望在 viewDidLayoutSubviews()
中进行。来自 Apple 的文档:
viewDidLayoutSubviews
When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method.
但是,如果我理解您实际想要做什么...
通过使用 UIStackView
,您可以避免使用 任何 代码。
将您的标签、视图、按钮等嵌入垂直 UIStackView
。将属性设置为:
Alignment: Fill (or Leading or Center as suits your layout)
Distribution: Equal Spacing
Spacing: 0
将堆栈视图的顶部约束到视图的顶部(加上任何所需的填充)并将底部约束到视图的底部(加上任何所需的填充)。
iPhone SE 大小的结果:
iPhone 8 尺寸的结果:
iPhone XS 码的结果:
还有,这里是 iPhone 8,还有一些不同高度的附加元素:
如您所见,元素之间的垂直间距相等,并且全部由堆栈视图处理。