-1

Here is my simple example. I have 1 vertical stack view with 1 subview. I want that subviews height to be based on the intrinsic height of the label within it, so that I can maintain a dynamic height for the entire stack view. How can this be done? Thanks

enter image description here

Gustavo Vollbrecht
  • 3,188
  • 2
  • 19
  • 37
natecraft1
  • 2,737
  • 9
  • 36
  • 56

2 Answers2

2

I think you did it right. But here is the keys:

  1. Don't set height for stackView.
  2. Set label top, bottom, left, trailing constraint to view.
  3. Run. It should be okay on simulator.

If you found label's height seems not wrapping (neither both on storyboard or simulator), then change label's Vertical Content Hugging Priority to 750.

enter image description here

axunic
  • 2,256
  • 18
  • 18
1

Try this code:

class DyanmicTextLabelViewController: UIViewController {

    private var didAddConstraint = false

    private let label: UILabel = {
        let view = UILabel()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.setContentHuggingPriority(.required, for: .vertical)
        view.setContentCompressionResistancePriority(.required, for: .vertical)
        view.text = "Layout anchors let you create constraints in an easy-to-read, compact format. They expose a number of methods for creating different types of constraints, as shown in Listing 13-1."
        view.numberOfLines = 0
        return view
    }()
    private lazy var container: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(label)
        view.backgroundColor = .red
        return view
    }()
    private lazy var stackview : UIStackView = {
        let view = UIStackView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.axis = .horizontal
        view.distribution = .fill
        view.addArrangedSubview(container)
        return view
    }()

    override func loadView() {
        super.loadView()

        view.addSubview(stackview)
        view.setNeedsUpdateConstraints()

        view.backgroundColor = .white
    }


    override func updateViewConstraints() {
        super.updateViewConstraints()

        if didAddConstraint == false {
            didAddConstraint = true

            // stackview constraints
            stackview.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true

            let topAnchor = stackview.topAnchor.constraint(equalTo: view.topAnchor)
            topAnchor.constant = 20
            topAnchor.isActive = true

            stackview.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true

            // label constraint
            // example for giving label a left padding
            let labelLeft = label.leftAnchor.constraint(equalTo: container.leftAnchor)
            labelLeft.constant = 16.0
            labelLeft.isActive = true

            label.topAnchor.constraint(equalTo: container.topAnchor).isActive = true
            label.rightAnchor.constraint(equalTo: container.rightAnchor).isActive = true
            label.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true
        }
    }
}

The important part here is the initialization of stackview, label & constraint set on label

label initialization

private let label: UILabel = {
    let view = UILabel()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.setContentHuggingPriority(.required, for: .vertical)
    view.setContentCompressionResistancePriority(.required, for: .vertical)
    view.text = "Layout anchors let you create constraints in an easy-to-read, compact format. They expose a number of methods for creating different types of constraints, as shown in Listing 13-1."
    view.numberOfLines = 0
    return view
}()

stackview initialization

private lazy var stackview : UIStackView = {
    let view = UIStackView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.axis = .horizontal
    view.distribution = .fill
    view.addArrangedSubview(container)
    return view
}()

label constraint

// label constraint
// example for giving label a left padding
let labelLeft = label.leftAnchor.constraint(equalTo: container.leftAnchor)
labelLeft.constant = 16.0
labelLeft.isActive = true

label.topAnchor.constraint(equalTo: container.topAnchor).isActive = true
label.rightAnchor.constraint(equalTo: container.rightAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true

This settings could be easily translated to storyboard.

Ratul Sharker
  • 7,484
  • 4
  • 35
  • 44