以编程方式创建具有2个对齐标签的水平UIStackView

时间:2017-11-09 04:12:20

标签: ios autolayout uistackview programmatically-created

我想要2个标签(比如leftLabel,rightLabel)并将它们水平放置,使得leftLabel伸展,rightLabel只适合单个字符图标(例如“>”)。因此两个标签布局都是合理的。像这样......

enter image description here

这是我的代码 -

class StackViewController: UIViewController {
    /// Main vertical outer/container stack view that pins its edges to this view in storyboard (i.e. full screen)
    @IBOutlet weak private var containerStackView: UIStackView!

    private var leftLabel: UILabel = {
        let leftLabel = UILabel(frame: .zero)
        leftLabel.font = .preferredFont(forTextStyle: .body)
        leftLabel.numberOfLines = 0 // no text truncation, allows wrap
        leftLabel.backgroundColor = .orange
        return leftLabel
    }()
    private var rightLabel: UILabel = {
        let rightLabel = UILabel(frame: .zero)
        rightLabel.font = .preferredFont(forTextStyle: .body)
        // Set CHCR as high so that label sizes itself to fit the text
        rightLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .horizontal)
        rightLabel.setContentCompressionResistancePriority(UILayoutPriorityDefaultHigh, for: .horizontal)
        rightLabel.backgroundColor = .green
        return rightLabel
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        prepareAndLoadSubViews()
        // Note, the text required to be set in viewDidAppear, not viewDidLoad, otherwise rightLabel stretches to fill!!
        leftLabel.text = "This is left label text that may go in multiple lines"
        rightLabel.text = ">"   // Always a single character
    }

    /// Dynamically creates a horizontal stack view, with 2 labels, in the container stack view
    private func prepareAndLoadSubViews() {
        /// Prepare the horizontal label stack view and add the 2 labels
        let labelStackView = UIStackView(arrangedSubviews: [leftLabel, rightLabel])
        labelStackView.axis = .horizontal
        labelStackView.distribution = .fillProportionally
        labelStackView.alignment = .top
        containerStackView.addArrangedSubview(labelStackView)
        containerStackView.addArrangedSubview(UIView())
    }
}

其中给出了以下结果(即视图调试器中的leftLabel宽度为0) -

enter image description here

注意:如果我在viewDidAppear中移动文本集代码,那么它可以正常工作。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // Note, the text required to be set in viewDidAppear, not viewDidLoad, otherwise rightLabel stretches to fill!!
    leftLabel.text = "This is left label text that may go in multiple lines"
    rightLabel.text = ">"   // Always a single character
}

为什么呢? 而且,我们可以在viewDidLoad之前设置内容拥抱/压缩阻力优先级吗?

1 个答案:

答案 0 :(得分:0)

我玩了很多代码,但我也无法使用它。我认为这是将UIStackView添加到另一个UIStackView时发生的错误。当您只有一个UIStackView时,您的代码就可以正常工作。

所以我无法为您的案例提供修复,但恕我直言,您根本不需要为{2}标签使用UIStackViewUIStackView非常棒,如果您有多个已隐藏和显示的子视图,并且需要自动排列。只有两个"静态"标签我认为这有点过分。

您可以将两个标签添加到UIView,然后将布局限制设置为标签,从而实现您的目标。这很简单:

class StackViewController: UIViewController {

    @IBOutlet weak var containerStackView: UIStackView!

    private var leftLabel: UILabel = {
        let leftLabel = UILabel(frame: .zero)
        leftLabel.font = .preferredFont(forTextStyle: .body)
        leftLabel.numberOfLines = 0
        leftLabel.backgroundColor = .orange
        leftLabel.translatesAutoresizingMaskIntoConstraints = false
        leftLabel.numberOfLines = 0
        return leftLabel
    }()
    private var rightLabel: UILabel = {
        let rightLabel = UILabel(frame: .zero)
        rightLabel.font = .preferredFont(forTextStyle: .body)
        rightLabel.setContentHuggingPriority(UILayoutPriority.required, for: .horizontal)
        rightLabel.backgroundColor = .green
        rightLabel.translatesAutoresizingMaskIntoConstraints = false
        return rightLabel
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        prepareAndLoadSubViews()
        leftLabel.text = "This is left label text that may go in multiple lines"
        rightLabel.text = ">"
    }

    private func prepareAndLoadSubViews() {
        let labelContainerView = UIView()
        labelContainerView.addSubview(leftLabel)
        labelContainerView.addSubview(rightLabel)

        NSLayoutConstraint.activate([
            leftLabel.leadingAnchor.constraint(equalTo: labelContainerView.leadingAnchor),
            leftLabel.topAnchor.constraint(equalTo: labelContainerView.topAnchor),
            leftLabel.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor),

            rightLabel.leadingAnchor.constraint(equalTo: leftLabel.trailingAnchor),
            rightLabel.topAnchor.constraint(equalTo: labelContainerView.topAnchor),
            rightLabel.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor),
            rightLabel.trailingAnchor.constraint(equalTo: labelContainerView.trailingAnchor)
        ])

        containerStackView.addArrangedSubview(labelContainerView)
        containerStackView.addArrangedSubview(UIView())
    }
}