如何以编程方式创建等效的 SwiftUI 堆栈视图分隔符

Posted

技术标签:

【中文标题】如何以编程方式创建等效的 SwiftUI 堆栈视图分隔符【英文标题】:How to create the equivalent of a SwiftUI stack view spacer programmatically 【发布时间】:2021-02-26 18:43:18 【问题描述】:

我正在尝试在不使用 SwiftUI 的情况下在代码中重新创建第一个 SwiftUI Tutorial。在示例中,它提到使用Spacer“指示布局使用设备的全宽”:

VStack 
  Text("Turtle Rock")
  HStack 
    Text("Joshua Tree National Park")
    Spacer()
    Text("California")
  

对于VStackHStackText 视图,我可以轻松使用UIStackViewUILabel。但是对于Spacer,我似乎在标准库中找不到任何等价物(没有UISpacer 或类似的东西),这让我觉得这是SwiftUI 的定制。在教程中,它描述了 Spacer 的工作原理:

spacer 扩展以使其包含视图使用其父视图的所有空间,而不是仅由其内容定义其大小。

那么如何以编程方式重新创建此Spacer 视图的功能?我是否只是向 UIStackView 添加约束以使其全宽?或者有没有办法向 UIStackView 添加一个子视图,使其表现得像在 SwiftUI 中一样?

【问题讨论】:

可以设置堆栈视图分布=.equalSpacing 您可以使用 UILayoutGuide 作为容器。这有帮助吗-:developer.apple.com/documentation/uikit/uilayoutguide 【参考方案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,因为它没有设置宽度限制。我只是垂直测试了这个。但是,您应该注意UIStackViewSwiftUI.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

我认为通过这种方式,您可以使用垫片大小/布局和堆栈分布/对齐来获得所需的空间。

【讨论】:

以上是关于如何以编程方式创建等效的 SwiftUI 堆栈视图分隔符的主要内容,如果未能解决你的问题,请参考以下文章

尝试以编程方式使用嵌套的 Stack 视图制作网格

以编程方式创建 UILabel 堆栈

Swift - 以编程方式向堆栈视图添加标签

如何以编程方式在滚动视图中嵌入堆栈视图

以编程方式导航到 SwiftUI 中的新视图

以编程方式创建布局,使用堆栈视图和约束不起作用