I have a UIScrollView, nested inside of which in one content view and it has two child views nested, a regular UIView with a known height, and a container view with dynamic height depending on is content. Like so:
The view looks like this:
My constraints are setup as follows:
The Scroll View is constrained to the trailing, leading, top and bottom edges of its superview (i.e. the View)
The Content View is constrained to the trailing, leading, top and bottom edges of its superview (i.e. the Scroll View) It also has a width constraint equal to the main view (i.e. the View) so the width of the scrollview is the same as the screen width.
The top view is constrained to the leading, trailing and top edges of its superview (i.e. the Content View)
The Container View is constrained to the trailing, leading and bottom edges of its superview (the Content View) Its top edge is also constrained to the bottom edge of the Top View.
The view hierarchy of the Container View looks like this:
The top left label is constrained to the trailing, leading and top edges of its superview. The bottom right label is constrained to the trailing, leading and bottom edges of its superview. The top label has a vertical constraint to the bottom label. I've made this vertical constraint extra large for the purpose of my tests (1000 points).
This should give the content view a height of ~1000 points.
My understanding was with a height now resolved for the container view, that the Content View would resize to the height of the Top View + the height of the Container View.
But IB complains with the following:
It wants to resize the Container View and give it a height of 0. If I give the Container View an explicit height then everything works as expected but this is not what I need want since the Container View can dynamically change depending on its content size.
Any help is appreciated!
There were two things I found that helped me work around this same issue.
I want the container view to resize itself, but IB wants an explicit height on the container view. Since IB doesn't know anything about the content of the view, it has no way of knowing the content of the container view can size itself. The simplest way to do that is to set a Placeholder Intrinsic Content Size
from the Size Inspector for the container view:
This effectively results in making IB happy without applying any height constraint. Another option is to add a "Remove at build time" height constraint on the container.
The root view of the child view controller defaults to using an AutoresizingMask
, as is standard for the topmost view in any UIViewController
. My solution to this is to disable use of AutoresizingMask
in prepareForSegue
, when the child view controller is added. Try the following in the parent view controller:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let childViewController = segue.destination as? ChildViewControllerClass {
childViewController.view.translatesAutoresizingMaskIntoConstraints = false
}
}
Making the change in the parent view ensures that if the child view is re-used elsewhere inside a UINavigationController
, the view will be sized correctly.
Before I made that change, I kept getting AutoLayout errors conflicting with constraints called UIView-Encapsulated-Layout-Height
, which I believe is the name for constraints derived from AutoresizingMask
based layout on the root UIViewController
view.
You must provide enough constraints information in the UIScrollView so that it can calculate its contentSize. For you case, you must provide height constraint for you container view. You can IBOutlet the height constraint and update its value accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With