UIStackView:将子视图推到边缘("Unlimited" 间距)

UIStackView: push subviews to the edges ("Unlimited" spacing)

我正在使用 UIStackView 定义列表的布局。

我正在尝试实现类似这样的效果:

||Item1---spacing---Item2||

因此,这两个项目被推到 UIStackView 的两侧。

但是,这些项目以 distributionalignment 的所有可能组合组合在一起:

||Item1-Item2-----spacing-----||

我尝试设置一个较大的间距值,即 500。在这种情况下,Item2 就会离开屏幕。

有没有办法把"tie"Item1Item2左右两边UIStackView,同时允许间距根据屏幕宽度变化?

实现此目的的一种可能方法是在两个视图之间添加一个 'spacing' 视图,并确保视图的拥抱优先级大于间距优先级(当然它们会有有效的固有大小或定义其宽度的约束)。这是我放在一起进行测试的快速游乐场:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let label1 = UILabel()
        label1.translatesAutoresizingMaskIntoConstraints = false
        label1.text = "Left"
        label1.backgroundColor = .red
        label1.setContentHuggingPriority(.required, for: .horizontal)

        let label2 = UILabel()
        label2.translatesAutoresizingMaskIntoConstraints = false
        label2.text = "Right"
        label2.backgroundColor = .green
        label2.setContentHuggingPriority(.required, for: .horizontal)

        let stack = UIStackView(arrangedSubviews: [label1, UIView(), label2])
        stack.translatesAutoresizingMaskIntoConstraints = false
        stack.distribution = .fill
        stack.axis = .horizontal

        view.addSubview(stack)

        stack.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        stack.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        stack.topAnchor.constraint(equalTo: view.topAnchor).isActive = true


        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

产生这个:


注意:有趣的是,即使根本没有设置标签的拥抱优先级,我示例中的结果也保持不变(我很想知道为什么顺便说一句,这正在发生。我的猜测是因为它们具有非零的固有内容大小(?)),但决定保留代码以演示其背后的原理。

UIStackView 折叠并将其 intrinsicContentSize 设置为其子视图和间距的总和。

通过向 "stretch" UIStackView 添加一组约束,我设法获得了我想要的效果:

hStack.snp.makeConstraints { (make) in
  make.leading.trailing.equalToSuperview()
}