当特征收集发生变化时,就会产生约束冲突,好像堆栈视图轴没有变化

时间:2019-01-28 18:08:05

标签: swift uikit nslayoutconstraint ios-autolayout uitraitcollection

我有一个带有两个控件的stackview。

当UI不受垂直约束时: Vertical1

垂直限制用户界面时:Horizontal1

我得到了两个UI,如图所示。第一次显示UI时没有约束冲突。但是,当我从垂直约束变为Vertical = Regular时,会遇到约束冲突。

当我注释掉stackview空间(请参见下面的代码注释)时,我没有遇到约束冲突。

class ViewController: UIViewController {

    var rootStack: UIStackView!
    var aggregateStack: UIStackView!
    var field1: UITextField!
    var field2: UITextField!
    var f1f2TrailTrail: NSLayoutConstraint!

    override func viewDidLoad() {

        super.viewDidLoad()
        view.backgroundColor = .white
        createIntializeViews()
        createInitializeAddStacks()
    }

    private func createIntializeViews() {

        field1 = UITextField()
        field2 = UITextField()
        field1.text = "test 1"
        field2.text = "test 2"
    }

    private func createInitializeAddStacks() {

        rootStack = UIStackView()             

        aggregateStack = UIStackView()

        // If I comment out the following, there are no constraint conflicts
        aggregateStack.spacing = 2            

        aggregateStack.addArrangedSubview(field1)
        aggregateStack.addArrangedSubview(field2)
        rootStack.addArrangedSubview(aggregateStack)

        view.addSubview(rootStack)

        rootStack.translatesAutoresizingMaskIntoConstraints = false
        aggregateStack.translatesAutoresizingMaskIntoConstraints = false
        field1.translatesAutoresizingMaskIntoConstraints = false
        field2.translatesAutoresizingMaskIntoConstraints = false

        f1f2TrailTrail = field2.trailingAnchor.constraint(equalTo: field1.trailingAnchor)
    }


    override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

        super.traitCollectionDidChange(previousTraitCollection)

        if traitCollection.verticalSizeClass == .regular {
            aggregateStack.axis = .vertical
            f1f2TrailTrail.isActive = true
        } else if traitCollection.verticalSizeClass == .compact {
            f1f2TrailTrail.isActive = false
            aggregateStack.axis = .horizontal
        } else {
            print("Unexpected")
        }
    }
}

约束冲突在这里-

(
    "<NSLayoutConstraint:0x600001e7d1d0 UITextField:0x7f80b2035000.trailing == UITextField:0x7f80b201d000.trailing   (active)>",
    "<NSLayoutConstraint:0x600001e42800 'UISV-spacing' H:[UITextField:0x7f80b201d000]-(2)-[UITextField:0x7f80b2035000]   (active)>"
)

Will attempt to recover by breaking constraint 
    <NSLayoutConstraint:0x600001e42800 'UISV-spacing' H:[UITextField:0x7f80b201d000]-(2)-[UITextField:0x7f80b2035000]   (active)>

当我将输出放在www.wtfautolayout.com时,得到以下信息: Easier to Read Output

上图中显示的第二个约束使我认为在评估约束之前,未发生对stackview垂直轴的更改。

谁能告诉我我做错了什么或如何正确设置(最好没有情节提要)?

[EDIT]文本字段的后边缘对齐以具有以下功能:

More of the form - portrait

More of the form - landscape

2 个答案:

答案 0 :(得分:0)

Sub Compare() Dim WS1 As Worksheet: Set WS1 = ThisWorkbook.Sheets("Sheet1") Dim WS2 As Worksheet: Set WS2 = ThisWorkbook.Sheets("SHeet2") Dim LR1 As Long, LR2 As Long, WS1_Cell As Range, WS2_Cell As Range LR1 = WS1.Range("A" & WS1.Rows.Count).End(xlUp).Row LR2 = WS2.Range("A" & WS2.Rows.Count).End(xlUp).Row For Each WS1_Cell In WS1.Range("A1:A" & LR1) For Each WS2_Cell In WS2.Range("A1:A" & LR2) If WS1_Cell = WS2_Cell Then WS1_Cell.Offset(, 7).Value = WS2_Cell.Offset(, 7).Value End If Next WS2_Cell Next WS1_Cell End Sub 添加到UIView时,stackView将基于分配给stackView的属性(UIStackViewaxis,{ {1}},alignment)。如@DonMag所述,您正在distribution视图中为spacing添加约束。 textField将基于其属性添加其自己的约束。通过删除该约束和激活/停用代码,约束冲突消失了。

我使用您的代码创建了一个小示例,并将一些背景视图添加到stackViews中,以便您可以更轻松地查看更改各种属性时发生的情况。仅出于说明目的,我将aggregateStack固定在视图控制器视图的边缘,以使其可见。

aggregateStack

enter image description here

答案 1 :(得分:0)

情侣笔记...

  • “嵌套”堆栈视图存在一个固有的问题,导致约束冲突。通过将受影响元素的优先级设置为999(而不是默认的1000)可以避免这种情况。
  • 您的布局变得有点复杂...标签“附加”到文本字段;元素必须在纵向的两条“线”上或在横向的一条“线”上;高度不同的“多元素线”中的一个元素(步进器);等等。
  • 要使“ field2”和“ field3”的大小相等,即使它们不是同一子视图的子视图,也需要将它们的宽度限制为相等。这是完全有效的,只要它们是相同的视图层次的后代。
  • Stackview很棒---除非不是那样。我几乎建议仅使用约束。您需要添加更多约束,但可能可以避免堆栈视图出现某些问题。

但是,这里有一个例子,应该让你对你的方式。

我添加了一个名为UIStackView的{​​{1}}子类...它在堆栈视图中设置了Label-above-Field。比将其混入所有其他布局代码中更干净。

LabeledFieldStackView

结果:

enter image description here

enter image description here