在viewWillAppear

时间:2019-02-21 09:21:15

标签: ios swift autolayout nslayoutconstraint

我在uiview的中央有一个viewcontroller。在该uilabel的上方(A)和下方(B)有uiview

我想以编程方式更改此uiview的底部约束,以使uiview上方和下方的距离随着屏幕尺寸的变化而彼此相等。因此,计算顶部uiviewuilabel的底部之间的距离(A)和底部uiviewuilabel的顶部之间的距离(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

下面是所需结果的之前/之后示例,其中紫色uiview对底部橙色uilabel具有底部约束。例如,当屏幕尺寸增加时,我希望底部约束具有与紫色uiview和顶部橙色uilabel之间的距离相同的常数。顶部uilabel的顶部具有顶部约束,底部uilabel的底部具有底部约束。 Example

5 个答案:

答案 0 :(得分:0)

在更新约束后写入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()

答案 1 :(得分:0)

当您使用View时,已经出现了当用户看到VeiwController时, 请改用viewDidLoad,您不能使用viewWillAppear,因为尚未加载View。

用于:

override func viewDidLoad() {
    super.viewDidLoad()
}

您可以尝试致电

self.view.layoutIfNeeded()

答案 2 :(得分:0)

当我想以编程方式设置约束时,我通常是这样进行的:

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

答案 3 :(得分:0)

您可以为此使用调度队列:

      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()
    }

答案 4 :(得分:0)

尝试回答您的问题:

您是对的,该自动布局尚未完成在viewDidLoad()甚至viewWillAppear()中的工作。通常,当您需要进行这样的布局调整时,您想在viewDidLayoutSubviews()中进行。来自Apple的文档:

  

viewDidLayoutSubviews

     

当视图控制器的视图的边界发生变化时,视图将调整其子视图的位置,然后系统调用此方法。

但是,如果我了解您的实际意图...

通过使用UIStackView,您可以避免使用任何代码。

将标签,视图,按钮等嵌入垂直UIStackView中。将属性设置为:

Alignment: Fill   (or Leading or Center as suits your layout)
Distribution: Equal Spacing
Spacing: 0

将堆栈视图的顶部约束到视图顶部(加上所需的填充),将底部约束到视图底部(加上所需的填充)。

iPhone SE大小的结果:

enter image description here

iPhone 8尺寸的结果:

enter image description here

iPhone XS尺寸的结果:

enter image description here

而且,这是iPhone 8,其中还有一些不同高度的其他元素:

enter image description here

如您所见,元素之间具有相等的垂直间距,并且全部由堆栈视图处理。