Search code examples
iosiphoneswiftview

UIStackView height is not 0 when arranged subviews' heights are all zero


I suppose the height of a vertical UIStackView should be the total height of its arranged views. However, when I change the frame height of all arranged views to 0, the frame height of the UIStackView is still having a non-zero value even view.layoutIfNeeded() is called and all the arranged views are disappeared. I have also tried to set the Clip to Bounds of the UIStackView to true but it stills does not work. Here is my code:

override func viewDidLoad() {
  super.viewDidLoad()
  print("Before --- UIStackView.frame.height: \(stackView.frame.height)")
  print("Before --- firstLabel.frame.height: \(firstLabel.frame.height)")
  print("Before --- secondLabel.frame.height: \(secondLabel.frame.height)")
  print("Before --- thirdLabel.frame.height: \(thirdLabel.frame.height)")
  print("Before --- forthLabel.frame.height: \(forthLabel.frame.height)")
  for view in stackView.arrangedSubviews {
    view.frame = CGRect(x: view.frame.origin.x, y: view.frame.origin.y, width: view.frame.width, height: 0)
  }
  print("===================================")
  print("After --- UIStackView.frame.height: \(stackView.frame.height)")
  print("After --- firstLabel.frame.height: \(firstLabel.frame.height)")
  print("After --- secondLabel.frame.height: \(secondLabel.frame.height)")
  print("After --- thirdLabel.frame.height: \(thirdLabel.frame.height)")
  print("After --- forthLabel.frame.height: \(forthLabel.frame.height)")
  view.layoutIfNeeded()
}

Here is the log:

Before --- UIStackView.frame.height: 82.0
Before --- firstLabel.frame.height: 20.5
Before --- secondLabel.frame.height: 20.5
Before --- thirdLabel.frame.height: 20.5
Before --- forthLabel.frame.height: 20.5
 ===================================
After --- UIStackView.frame.height: 82.0
After --- firstLabel.frame.height: 0.0
After --- secondLabel.frame.height: 0.0
After --- thirdLabel.frame.height: 0.0
After --- forthLabel.frame.height: 0.0

Solution

  • I think you are using a mixture of auto layout and setting frames manually. To see that everything works as expected instead of setting the labels' frames to a height of 0 set their text property to an empty string (which results in an intrinsicContentSize with a height of 0):

    // Your print statements BEFORE...
    
    for arrangedSubview in stackView.arrangedSubviews {
        if let label = arrangedSubview as? UILabel {
            label.text = ""
        }
    }
    view.layoutIfNeeded()
    
    // Your print statements AFTER...
    

    Results in:

    result