Search code examples
iosswiftuiview

How to corrently use UIViews systemLayoutSizeFitting to get the height to show all subviews using a given width?


TD;DR

It seems that in some cases systemLayoutSizeFitting does not return the correct height to correctly show / position all subviews of a view. Am I using systemLayoutSizeFitting wrong or is there some other way to avoid this?


Long story:

The XIB file of a UIViewController does not only contain the main view but also a number of other views which are added to the view controllers view at runtime. All these additional views should get the same height when they are added to the view controllers view.

The views might look like this: A simple container view holding some subviews which are stacked on top of each other.

enter image description here

Since the height of the container view should be flexible, the vertical spacing between the bottom button and the lable above it, uses a grater-than constraint.

To give all views the same height, I tried to measure the necessary height of each view using systemLayoutSizeFitting:

@IBOutlet var pageViews: [UIView]!

override func viewDidLoad() {
    super.viewDidLoad()

    var maxHeight: CGFloat = 0
    for pageView in pageViews {
        // Add pageView somewhere on view and give it leading, trailing and top
        // constraint, but no height constraint yet.
        addToView(pageView)
        
        maxHeight = max(maxHeight, pageView.systemLayoutSizeFitting(CGSize(width: view.frame.width, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel).height)
    }
    
    for pageView in pageViews {
        // Give all pageViews the same height
        pageView.heightAnchor.constraint(equalToConstant: maxHeight).isActive = true
    }
}

This does not work, when the label text becomes to long:

enter image description here

In the right example the height is not large enough and thus the button is squeezed. I can counter act this by raising the vertical compression resistance of the button, however in this case the other controls (e.g. the title label) is squeezed...

Why is this? Why does not systemLayoutSizeFitting return a height which is sufficent to show all controls without any squeezing?


Solution

  • Its actually smash button's height when label text is getting bigger . You are setting top and bottom constraints but button height is not declared so when label getting bigger , view basically say "I can reduce button height before updating my height , I have space.Bottom and top constraints are still same , didn't effect."

    Giving the constant height constraints of button might be fix your issue.