【问题标题】:How to create the equivalent of a SwiftUI stack view spacer programmatically如何以编程方式创建等效的 SwiftUI 堆栈视图分隔符
【发布时间】:2021-02-26 18:43:18
【问题描述】:
我正在尝试在不使用 SwiftUI 的情况下在代码中重新创建第一个 SwiftUI Tutorial。在示例中,它提到使用Spacer“指示布局使用设备的全宽”:
VStack {
Text("Turtle Rock")
HStack {
Text("Joshua Tree National Park")
Spacer()
Text("California")
}
}
对于VStack、HStack 和Text 视图,我可以轻松使用UIStackView 和UILabel。但是对于Spacer,我似乎在标准库中找不到任何等价物(没有UISpacer 或类似的东西),这让我觉得这是SwiftUI 的定制。在教程中,它描述了 Spacer 的工作原理:
spacer 扩展以使其包含视图使用其父视图的所有空间,而不是仅由其内容定义其大小。
那么如何以编程方式重新创建此Spacer 视图的功能?我是否只是向 UIStackView 添加约束以使其全宽?或者有没有办法向 UIStackView 添加一个子视图,使其表现得像在 SwiftUI 中一样?
【问题讨论】:
标签:
objective-c
swift
swiftui
uikit
【解决方案1】:
我已经使用虚拟UIView() 解决了解决方案,它使用低优先级设置了大常量widthConstraint - 这确保 UIView 将尽可能地增长,但不会增长超过superview 约束,因为它具有较低的优先级。
例子:
let titleLabel = UILabel()
titleLabel.text = "Joshua Tree National Park"
let spacer = UIView()
// maximum width constraint
let spacerWidthConstraint = spacer.widthAnchor.constraint(equalToConstant: .greatestFiniteMagnitude) // or some very high constant
spacerWidthConstraint.priority = .defaultLow // ensures it will not "overgrow"
spacerWidthConstraint.isActive = true
let descriptionLabel = UILabel()
descriptionLabel.text = "California"
UIStackView(arrangedSubviews: [titleLabel, spacer, descriptionLabel])
【解决方案2】:
只要分布设置为填充,普通的UIView() 可以替换SwiftUI.Spacer,因为它没有设置宽度限制。我只是垂直测试了这个。但是,您应该注意UIStackView 和SwiftUI.HStack 执行的布局实际上并不是相同的步骤,尽管最终结果可能看起来相似;需要调查的东西。
【解决方案3】:
斯威夫特 5
您可以为UIView 创建一个扩展,以通过这种方式创建一个分隔符:
extension UIView {
static func spacer(size: CGFloat = 10, for layout: NSLayoutConstraint.Axis = .horizontal) -> UIView {
let spacer = UIView()
if layout == .horizontal {
spacer.widthAnchor.constraint(equalToConstant: size).isActive = true
} else {
spacer.heightAnchor.constraint(equalToConstant: size).isActive = true
}
return spacer
}
}
之后,您可以通过以下方式将垫片添加到堆栈中:
// ... some code
let stack = UIStackView(arrangedSubviews: [UIView.spacer(), UILabel(), UIView.spacer(), UILabel(), UIView.spacer()])
stack.axis = .horizontal
stack.distribution = .equalSpacing
// For vertical stacks
let stack = UIStackView(arrangedSubviews: [UIView.spacer(for: .vertical), UILabel(), UIView.spacer(for: .vertical), UILabel(), UIView.spacer(for: .vertical)])
stack.axis = .vertical
stack.distribution = .equalSpacing
我认为通过这种方式,您可以使用垫片大小/布局和堆栈分布/对齐来获得所需的空间。