Home > OS >  How do I make a Swift UIStackView size dynamically based on content?
How do I make a Swift UIStackView size dynamically based on content?

Time:10-06

I have added the following UIStackView to my ViewController. As the views change the values of textOneLabel and textTwoLabel change.

With the following code the initial StackView is centered and the portions filled proportionally. However with subsequent text combinations the bounds of the StackView don't change, leaving the content off center. How can I change the StackView properties so it will adapt to the content and always stay centered?

headerStackView.axis = .horizontal
headerStackView.distribution = .fillProportionally
headerStackView.spacing = 8
headerStackView.layer.borderWidth = 1
headerStackView.layer.borderColor = UIColor.red.cgColor
    
headerStackView.translatesAutoresizingMaskIntoConstraints = false
headerStackView.topAnchor.constraint(equalTo: timerHeader.topAnchor, constant: 4).isActive = true
headerStackView.centerXAnchor.constraint(equalTo: timerHeader.centerXAnchor).isActive = true
    
headerStackView.addArrangedSubview(textOneLabel)
headerStackView.addArrangedSubview(textTwoLabel)

CodePudding user response:

First, forget you ever heard of .fillProportionally...

  • it doesn't do what you think it does
  • you'll encounter very unexpected layout issues if your stack view has spacing greater than Zero
  • if your stack view has no width (neither width anchor nor leading/trailing anchors), .fillProportionally doesn't do anything

So, change your .distribution to .fill.

Add these lines to control what auto-layout does with your labels:

    textOneLabel.setContentHuggingPriority(.required, for: .horizontal)
    textOneLabel.setContentCompressionResistancePriority(.required, for: .horizontal)

    textTwoLabel.setContentHuggingPriority(.required, for: .horizontal)
    textTwoLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
    

Now, your stackView FRAME will remain centered.

  • Related