gpt4 book ai didi

swift - 当特征集合发生变化时,会出现约束冲突,就像 stackview 轴没有变化一样

转载 作者:行者123 更新时间:2023-11-30 10:51:36 29 4
gpt4 key购买 nike

我有一个带有两个控件的堆栈 View 。

当 UI 不受垂直约束时: Vertical1

当 UI 受到垂直约束时:Horizontal1

我得到了如图所示的两个用户界面。当我第一次显示 UI 时,没有约束冲突。但是,当我从垂直约束变为垂直=常规时,我会遇到约束冲突。

当我注释掉 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 垂直轴的更改。

谁能告诉我我做错了什么或者如何正确设置它(最好没有 Storyboard)?

[编辑] 文本字段后缘对齐以具有以下内容:

More of the form - portrait

More of the form - landscape

最佳答案

情侣笔记...

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

但是,这里有一个示例,应该可以帮助您上路。

我添加了一个名为 LabeledFieldStackViewUIStackView 子类...它在堆栈 View 中设置 Label-above-Field。比将其混合在所有其他布局代码中要干净一些。

class LabeledFieldStackView: UIStackView {

var theLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()

var theField: UITextField = {
let v = UITextField()
v.translatesAutoresizingMaskIntoConstraints = false
v.borderStyle = .roundedRect
return v
}()

convenience init(with labelText: String, fieldText: String, verticalGap: CGFloat) {

self.init()

axis = .vertical
alignment = .fill
distribution = .fill
spacing = 2

addArrangedSubview(theLabel)
addArrangedSubview(theField)

theLabel.text = labelText
theField.text = fieldText

self.translatesAutoresizingMaskIntoConstraints = false

}

}

class LargentViewController: UIViewController {

var rootStack: UIStackView!

var fieldStackView1: LabeledFieldStackView!
var fieldStackView2: LabeledFieldStackView!
var fieldStackView3: LabeledFieldStackView!
var fieldStackView4: LabeledFieldStackView!

var stepper: UIStepper!

var fieldAndStepperStack: UIStackView!

var twoLineStack: UIStackView!

var fieldAndStepperStackWidthConstraint: NSLayoutConstraint!

// horizontal gap between elements on the same "line"
var horizontalSpacing: CGFloat!

// vertical gap between "lines"
var verticalSpacing: CGFloat!

// vertical gap between labels above text fields
var labelToFieldSpacing: CGFloat!

override func viewDidLoad() {

super.viewDidLoad()

view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)

horizontalSpacing = CGFloat(2)
verticalSpacing = CGFloat(8)
labelToFieldSpacing = CGFloat(2)

createIntializeViews()
createInitializeStacks()
fillStacks()

}

private func createIntializeViews() {

fieldStackView1 = LabeledFieldStackView(with: "label 1", fieldText: "field 1", verticalGap: labelToFieldSpacing)
fieldStackView2 = LabeledFieldStackView(with: "label 2", fieldText: "field 2", verticalGap: labelToFieldSpacing)
fieldStackView3 = LabeledFieldStackView(with: "label 3", fieldText: "field 3", verticalGap: labelToFieldSpacing)
fieldStackView4 = LabeledFieldStackView(with: "label 4", fieldText: "field 4", verticalGap: labelToFieldSpacing)

stepper = UIStepper()

}

private func createInitializeStacks() {

rootStack = UIStackView()
fieldAndStepperStack = UIStackView()
twoLineStack = UIStackView()

[rootStack, fieldAndStepperStack, twoLineStack].forEach {
$0?.translatesAutoresizingMaskIntoConstraints = false
}

// rootStack has spacing of horizontalSpacing (inter-line vertical spacing)
rootStack.axis = .vertical
rootStack.alignment = .fill
rootStack.distribution = .fill
rootStack.spacing = verticalSpacing

// fieldAndStepperStack has spacing of horizontalSpacing (space between field and stepper)
// and .alignment of .bottom (so stepper aligns vertically with field)
fieldAndStepperStack.axis = .horizontal
fieldAndStepperStack.alignment = .bottom
fieldAndStepperStack.distribution = .fill
fieldAndStepperStack.spacing = horizontalSpacing

// twoLineStack has inter-line vertical spacing of
// verticalSpacing in portrait orientation
// for landscape orientation, the two "lines" will be changed to one "line"
// and the spacing will be changed to horizontalSpacing
twoLineStack.axis = .vertical
twoLineStack.alignment = .leading
twoLineStack.distribution = .fill
twoLineStack.spacing = verticalSpacing

}

private func fillStacks() {

self.view.addSubview(rootStack)

// constrain rootStack Top, Leading, Trailing = 20
// no height or bottom constraint
NSLayoutConstraint.activate([
rootStack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
rootStack.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20.0),
rootStack.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20.0),
])

rootStack.addArrangedSubview(fieldStackView1)

fieldAndStepperStack.addArrangedSubview(fieldStackView2)
fieldAndStepperStack.addArrangedSubview(stepper)

twoLineStack.addArrangedSubview(fieldAndStepperStack)
twoLineStack.addArrangedSubview(fieldStackView3)

rootStack.addArrangedSubview(twoLineStack)

// fieldAndStepperStack needs width constrained to its superview (the twoLineStack) when
// in portrait orientation
// setting the priority to 999 prevents "nested stackView" constraint breaks
fieldAndStepperStackWidthConstraint = fieldAndStepperStack.widthAnchor.constraint(equalTo: twoLineStack.widthAnchor, multiplier: 1.0)
fieldAndStepperStackWidthConstraint.priority = UILayoutPriority(rawValue: 999)

// constrain fieldView3 width to fieldView2 width to keep them the same size
NSLayoutConstraint.activate([
fieldStackView3.widthAnchor.constraint(equalTo: fieldStackView2.widthAnchor, multiplier: 1.0)
])

rootStack.addArrangedSubview(fieldStackView4)

}

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

super.traitCollectionDidChange(previousTraitCollection)

if traitCollection.verticalSizeClass == .regular {
fieldAndStepperStackWidthConstraint.isActive = true
twoLineStack.axis = .vertical
twoLineStack.spacing = verticalSpacing
} else if traitCollection.verticalSizeClass == .compact {
fieldAndStepperStackWidthConstraint.isActive = false
twoLineStack.axis = .horizontal
twoLineStack.spacing = horizontalSpacing
} else {
print("Unexpected")
}
}

}

结果:

enter image description here

enter image description here

关于swift - 当特征集合发生变化时,会出现约束冲突,就像 stackview 轴没有变化一样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54407886/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com