解决 UILabel 约束问题
Resolving UILabel constraints issues
我是 UIKit 的初学者,我想在 UITableViewCell
中实现这种布局。
UIStackView1 由如下排列的子视图组成:
Header Label和Value Label都是UILabel,通过bottom-top anchoring连接。
UIStackView2类似,但Value Label是一个UITextField
出于某种原因,此代码生成空单元格。
func singleFieldsRow() -> UIView {
let viewContainer = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 0))
viewContainer.translatesAutoresizingMaskIntoConstraints = false
let stackView1: UIStackView = UIStackView()
stackView1.alignment = .leading
stackView1.axis = .vertical
stackView1.distribution = .fillProportionally
viewContainer.addSubview(stackView1)
// stackview1 constraints
stackView1.translatesAutoresizingMaskIntoConstraints = false
stackView1.leftAnchor.constraint(equalTo: viewContainer.leftAnchor).isActive = true
stackView1.bottomAnchor.constraint(equalTo: viewContainer.bottomAnchor).isActive = true
stackView1.rightAnchor.constraint(equalTo: viewContainer.rightAnchor).isActive = true
let stackView1Container: UIView = UIView()
viewContainer.addSubview(stackView1Container)
stackView1Container.translatesAutoresizingMaskIntoConstraints = false
stackView1Container.topAnchor.constraint(equalTo: viewContainer.topAnchor).isActive = true
stackView1Container.leftAnchor.constraint(equalTo: viewContainer.leftAnchor).isActive = true
stackView1Container.rightAnchor.constraint(equalTo: viewContainer.rightAnchor).isActive = true
stackView1Container.bottomAnchor.constraint(equalTo: stackView1.topAnchor).isActive = true
stackView1Container.widthAnchor.constraint(equalTo: viewContainer.widthAnchor).isActive = true
// stackview2
let stackView2: UIStackView = UIStackView()
stackView2.alignment = .leading
stackView2.axis = .vertical
stackView2.distribution = .equalCentering
stackView1Container.addSubview(stackView2)
stackView2.translatesAutoresizingMaskIntoConstraints = false
stackView2.topAnchor.constraint(equalTo: stackView1Container.topAnchor).isActive = true
stackView2.bottomAnchor.constraint(equalTo: stackView1Container.topAnchor).isActive = true
stackView2.leftAnchor.constraint(equalTo: stackView1Container.leftAnchor).isActive = true
stackView2.rightAnchor.constraint(equalTo: stackView1Container.rightAnchor).isActive = true
stackView2.widthAnchor.constraint(equalTo: stackView1Container.widthAnchor).isActive = true
for field in stack1Fields {
let fieldContainer = UIView()
let headerLabel: UILabel = UILabel()
let valueLabel: UILabel = UILabel()
headerLabel.text = field.title
headerLabel.numberOfLines = 0
headerLabel.adjustsFontSizeToFitWidth = true
valueLabel.text = field.value
valueLabel.numberOfLines = 0
valueLabel.adjustsFontSizeToFitWidth = true
fieldContainer.addSubview(headerLabel)
fieldContainer.addSubview(valueLabel)
headerLabel.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
headerLabel.topAnchor.constraint(equalTo: fieldContainer.topAnchor).isActive = true
headerLabel.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
headerLabel.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
valueLabel.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
valueLabel.bottomAnchor.constraint(equalTo: fieldContainer.bottomAnchor).isActive = true
valueLabel.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
valueLabel.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
stackView2.addArrangedSubview(fieldContainer)
}
for field in stack2Fields {
let fieldContainer = UIView()
let headerLabel: UILabel = UILabel()
headerLabel.text = productField.title
headerLabel.numberOfLines = 0
headerLabel.adjustsFontSizeToFitWidth = true
fieldContainer.addSubview(headerLabel)
let valueTextField: UITextField = UITextField()
valueTextField.text = productField.value
valueTextField.keyboardType = .default
valueTextField.placeholder = "Insert value"
valueTextField.translatesAutoresizingMaskIntoConstraints = false
fieldContainer.addSubview(valueTextField)
headerLabel.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
headerLabel.topAnchor.constraint(equalTo: fieldContainer.topAnchor).isActive = true
headerLabel.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
headerLabel.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
headerLabel.bottomAnchor.constraint(equalTo: valueTextField.topAnchor).isActive = true
valueTextField.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
valueTextField.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
valueTextField.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
valueTextField.bottomAnchor.constraint(equalTo: fieldContainer.bottomAnchor).isActive = true
editableStackView.addArrangedSubview(fieldContainer)
}
return viewContainer
}
你可以看到在UIStackView1的周围多了一个Container,因为有一段代码在UIStackView的右侧绘制了一个图像,但是对于这个例子来说并不重要。
如果我把 sizeToFit()
放在 UILabels
上我可以看到一些内容,但是 UIStackView1 是折叠的,这意味着每个 UILabel 都相互重叠。
我也在控制台上收到这些消息:
[LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x28157b4d0 h=--& v=--& UILabel:0x10501b790.width == 33.5 (active)>",
"<NSAutoresizingMaskLayoutConstraint:0x28157b700 h=--& v=--& UILabel:0x10501ca00.width == 66.5 (active)>",
"<NSLayoutConstraint:0x28154cc80 UILabel:0x10501b790.width == UIView:0x10501b620.width (active)>",
"<NSLayoutConstraint:0x28154cdc0 UILabel:0x10501ca00.width == UIView:0x10501b620.width (active)>"
)
UIStackView2
显示正确,UILabel
和 UITextField
一个接一个垂直放置。
但是有些 UITextField
显示不正确,运行时 window 给了我这个警告。
x-xcode-debug-views://7f82a530ff20?DBGViewDebuggerLaunchSessionParameter=7f82a530ff20: runtime: Layout Issues: Horizontal position is ambiguous for UITextField.
我是不是设置了太多限制?
非常感谢任何帮助。
无需为要添加到堆栈视图的所有视图添加约束。堆栈视图将处理约束。
我在我的代码中发现了几个入侵者。
这一行:
stackView2.bottomAnchor.constraint(equalTo: stackView1Container.topAnchor).isActive = true
必须改为:
stackView2.topAnchor.constraint(equalTo: stackView1Container.bottomAnchor).isActive = true
还有这个
stackView1Container.bottomAnchor.constraint(equalTo: stackView1.topAnchor).isActive = true
必须删除。
我是 UIKit 的初学者,我想在 UITableViewCell
中实现这种布局。
UIStackView1 由如下排列的子视图组成:
Header Label和Value Label都是UILabel,通过bottom-top anchoring连接。
UIStackView2类似,但Value Label是一个UITextField
出于某种原因,此代码生成空单元格。
func singleFieldsRow() -> UIView {
let viewContainer = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 0))
viewContainer.translatesAutoresizingMaskIntoConstraints = false
let stackView1: UIStackView = UIStackView()
stackView1.alignment = .leading
stackView1.axis = .vertical
stackView1.distribution = .fillProportionally
viewContainer.addSubview(stackView1)
// stackview1 constraints
stackView1.translatesAutoresizingMaskIntoConstraints = false
stackView1.leftAnchor.constraint(equalTo: viewContainer.leftAnchor).isActive = true
stackView1.bottomAnchor.constraint(equalTo: viewContainer.bottomAnchor).isActive = true
stackView1.rightAnchor.constraint(equalTo: viewContainer.rightAnchor).isActive = true
let stackView1Container: UIView = UIView()
viewContainer.addSubview(stackView1Container)
stackView1Container.translatesAutoresizingMaskIntoConstraints = false
stackView1Container.topAnchor.constraint(equalTo: viewContainer.topAnchor).isActive = true
stackView1Container.leftAnchor.constraint(equalTo: viewContainer.leftAnchor).isActive = true
stackView1Container.rightAnchor.constraint(equalTo: viewContainer.rightAnchor).isActive = true
stackView1Container.bottomAnchor.constraint(equalTo: stackView1.topAnchor).isActive = true
stackView1Container.widthAnchor.constraint(equalTo: viewContainer.widthAnchor).isActive = true
// stackview2
let stackView2: UIStackView = UIStackView()
stackView2.alignment = .leading
stackView2.axis = .vertical
stackView2.distribution = .equalCentering
stackView1Container.addSubview(stackView2)
stackView2.translatesAutoresizingMaskIntoConstraints = false
stackView2.topAnchor.constraint(equalTo: stackView1Container.topAnchor).isActive = true
stackView2.bottomAnchor.constraint(equalTo: stackView1Container.topAnchor).isActive = true
stackView2.leftAnchor.constraint(equalTo: stackView1Container.leftAnchor).isActive = true
stackView2.rightAnchor.constraint(equalTo: stackView1Container.rightAnchor).isActive = true
stackView2.widthAnchor.constraint(equalTo: stackView1Container.widthAnchor).isActive = true
for field in stack1Fields {
let fieldContainer = UIView()
let headerLabel: UILabel = UILabel()
let valueLabel: UILabel = UILabel()
headerLabel.text = field.title
headerLabel.numberOfLines = 0
headerLabel.adjustsFontSizeToFitWidth = true
valueLabel.text = field.value
valueLabel.numberOfLines = 0
valueLabel.adjustsFontSizeToFitWidth = true
fieldContainer.addSubview(headerLabel)
fieldContainer.addSubview(valueLabel)
headerLabel.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
headerLabel.topAnchor.constraint(equalTo: fieldContainer.topAnchor).isActive = true
headerLabel.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
headerLabel.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
valueLabel.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
valueLabel.bottomAnchor.constraint(equalTo: fieldContainer.bottomAnchor).isActive = true
valueLabel.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
valueLabel.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
stackView2.addArrangedSubview(fieldContainer)
}
for field in stack2Fields {
let fieldContainer = UIView()
let headerLabel: UILabel = UILabel()
headerLabel.text = productField.title
headerLabel.numberOfLines = 0
headerLabel.adjustsFontSizeToFitWidth = true
fieldContainer.addSubview(headerLabel)
let valueTextField: UITextField = UITextField()
valueTextField.text = productField.value
valueTextField.keyboardType = .default
valueTextField.placeholder = "Insert value"
valueTextField.translatesAutoresizingMaskIntoConstraints = false
fieldContainer.addSubview(valueTextField)
headerLabel.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
headerLabel.topAnchor.constraint(equalTo: fieldContainer.topAnchor).isActive = true
headerLabel.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
headerLabel.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
headerLabel.bottomAnchor.constraint(equalTo: valueTextField.topAnchor).isActive = true
valueTextField.widthAnchor.constraint(equalTo: fieldContainer.widthAnchor).isActive = true
valueTextField.leftAnchor.constraint(equalTo: fieldContainer.leftAnchor).isActive = true
valueTextField.rightAnchor.constraint(equalTo: fieldContainer.rightAnchor).isActive = true
valueTextField.bottomAnchor.constraint(equalTo: fieldContainer.bottomAnchor).isActive = true
editableStackView.addArrangedSubview(fieldContainer)
}
return viewContainer
}
你可以看到在UIStackView1的周围多了一个Container,因为有一段代码在UIStackView的右侧绘制了一个图像,但是对于这个例子来说并不重要。
如果我把 sizeToFit()
放在 UILabels
上我可以看到一些内容,但是 UIStackView1 是折叠的,这意味着每个 UILabel 都相互重叠。
我也在控制台上收到这些消息:
[LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "<NSAutoresizingMaskLayoutConstraint:0x28157b4d0 h=--& v=--& UILabel:0x10501b790.width == 33.5 (active)>", "<NSAutoresizingMaskLayoutConstraint:0x28157b700 h=--& v=--& UILabel:0x10501ca00.width == 66.5 (active)>", "<NSLayoutConstraint:0x28154cc80 UILabel:0x10501b790.width == UIView:0x10501b620.width (active)>", "<NSLayoutConstraint:0x28154cdc0 UILabel:0x10501ca00.width == UIView:0x10501b620.width (active)>" )
UIStackView2
显示正确,UILabel
和 UITextField
一个接一个垂直放置。
但是有些 UITextField
显示不正确,运行时 window 给了我这个警告。
x-xcode-debug-views://7f82a530ff20?DBGViewDebuggerLaunchSessionParameter=7f82a530ff20: runtime: Layout Issues: Horizontal position is ambiguous for UITextField.
我是不是设置了太多限制?
非常感谢任何帮助。
无需为要添加到堆栈视图的所有视图添加约束。堆栈视图将处理约束。
我在我的代码中发现了几个入侵者。
这一行:
stackView2.bottomAnchor.constraint(equalTo: stackView1Container.topAnchor).isActive = true
必须改为:
stackView2.topAnchor.constraint(equalTo: stackView1Container.bottomAnchor).isActive = true
还有这个
stackView1Container.bottomAnchor.constraint(equalTo: stackView1.topAnchor).isActive = true
必须删除。