如何在堆栈视图中居中对齐视图,而不拉伸任何视图或分布?
How to centre-align views in a stack view, and not stretch any of the views, or the distribution?
我正在构建自定义 longitude/latitude 选择器。视图看起来像:
textfield ° textfield ′ textfield ″ N|S
组件都在堆栈视图中。我希望文本字段的宽度能够自动适应内容。这是我正在使用的代码(实际布局代码不是很多。大部分是样板):
class DMSLongLatInputView : UIView {
private var degreeTextField: DMSLongLatTextField!
private var minuteTextField: DMSLongLatTextField!
private var secondTextField: DMSLongLatTextField!
var signSelector: UISegmentedControl!
let fontSize: CGFloat = 22
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
degreeTextField = DMSLongLatTextField()
minuteTextField = DMSLongLatTextField()
secondTextField = DMSLongLatTextField()
signSelector = UISegmentedControl(items: ["N", "S"])
signSelector.selectedSegmentIndex = 0
signSelector.setTitleTextAttributes([.font: UIFont.systemFont(ofSize: fontSize)], for: .normal)
[degreeTextField, minuteTextField, secondTextField].forEach { (tf) in
tf?.font = UIFont.monospacedDigitSystemFont(ofSize: fontSize, weight: .regular)
}
let degreeLabel = UILabel()
degreeLabel.text = "°"
let minuteLabel = UILabel()
minuteLabel.text = "′"
let secondLabel = UILabel()
secondLabel.text = "″"
[degreeLabel, minuteLabel, secondLabel].forEach {
l in l.font = UIFont.systemFont(ofSize: fontSize)
}
let stackView = UIStackView(arrangedSubviews:
[degreeTextField,
degreeLabel,
minuteTextField,
minuteLabel,
secondTextField,
secondLabel,
signSelector
])
stackView.arrangedSubviews.forEach { (v) in
// I was hoping that this would make the widths of the stack view's subviews automatically
// fit the content
v.setContentCompressionResistancePriority(.required, for: .horizontal)
v.setContentHuggingPriority(.required, for: .horizontal)
}
stackView.axis = .horizontal
stackView.alignment = .center
stackView.distribution = .fill
addSubview(stackView)
stackView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
stackView.translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear
}
}
fileprivate class DMSLongLatTextField: UITextField, UITextFieldDelegate {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
backgroundColor = .tertiarySystemFill
placeholder = "00"
borderStyle = .none
textAlignment = .right
}
}
这会产生:
尽管我将内容拥抱优先级设置为 .required
,但第一个文本字段被拉长了很多。我希望第一个文本字段只有两位数那么宽,因为那是它的占位符的宽度。
我怀疑这是因为我用错了distribution
,但我尝试了所有其他4个发行版,但其中none个得到了我想要的结果。例如,.equalSpacing
和 spacing = 0
给出了这个结果(从调试器中的 UI 层次检查器可以看出):
很明显间距不是0!我希望所有子视图尽可能靠近,并保持居中对齐。我该怎么做?
您正在堆栈视图上设置前导和尾随...换句话说,您是在告诉 auto-layout 到:
“用子视图填充屏幕的宽度。”
将您的约束更改为:
stackView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
//stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
//stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
这应该使您的堆栈视图及其子视图水平居中。
我正在构建自定义 longitude/latitude 选择器。视图看起来像:
textfield ° textfield ′ textfield ″ N|S
组件都在堆栈视图中。我希望文本字段的宽度能够自动适应内容。这是我正在使用的代码(实际布局代码不是很多。大部分是样板):
class DMSLongLatInputView : UIView {
private var degreeTextField: DMSLongLatTextField!
private var minuteTextField: DMSLongLatTextField!
private var secondTextField: DMSLongLatTextField!
var signSelector: UISegmentedControl!
let fontSize: CGFloat = 22
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
degreeTextField = DMSLongLatTextField()
minuteTextField = DMSLongLatTextField()
secondTextField = DMSLongLatTextField()
signSelector = UISegmentedControl(items: ["N", "S"])
signSelector.selectedSegmentIndex = 0
signSelector.setTitleTextAttributes([.font: UIFont.systemFont(ofSize: fontSize)], for: .normal)
[degreeTextField, minuteTextField, secondTextField].forEach { (tf) in
tf?.font = UIFont.monospacedDigitSystemFont(ofSize: fontSize, weight: .regular)
}
let degreeLabel = UILabel()
degreeLabel.text = "°"
let minuteLabel = UILabel()
minuteLabel.text = "′"
let secondLabel = UILabel()
secondLabel.text = "″"
[degreeLabel, minuteLabel, secondLabel].forEach {
l in l.font = UIFont.systemFont(ofSize: fontSize)
}
let stackView = UIStackView(arrangedSubviews:
[degreeTextField,
degreeLabel,
minuteTextField,
minuteLabel,
secondTextField,
secondLabel,
signSelector
])
stackView.arrangedSubviews.forEach { (v) in
// I was hoping that this would make the widths of the stack view's subviews automatically
// fit the content
v.setContentCompressionResistancePriority(.required, for: .horizontal)
v.setContentHuggingPriority(.required, for: .horizontal)
}
stackView.axis = .horizontal
stackView.alignment = .center
stackView.distribution = .fill
addSubview(stackView)
stackView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
stackView.translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear
}
}
fileprivate class DMSLongLatTextField: UITextField, UITextFieldDelegate {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
backgroundColor = .tertiarySystemFill
placeholder = "00"
borderStyle = .none
textAlignment = .right
}
}
这会产生:
尽管我将内容拥抱优先级设置为 .required
,但第一个文本字段被拉长了很多。我希望第一个文本字段只有两位数那么宽,因为那是它的占位符的宽度。
我怀疑这是因为我用错了distribution
,但我尝试了所有其他4个发行版,但其中none个得到了我想要的结果。例如,.equalSpacing
和 spacing = 0
给出了这个结果(从调试器中的 UI 层次检查器可以看出):
很明显间距不是0!我希望所有子视图尽可能靠近,并保持居中对齐。我该怎么做?
您正在堆栈视图上设置前导和尾随...换句话说,您是在告诉 auto-layout 到:
“用子视图填充屏幕的宽度。”
将您的约束更改为:
stackView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
//stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
//stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
这应该使您的堆栈视图及其子视图水平居中。