Sizing a Container View with a Controller of Dynamic Size Inside a Scrollview

Sizing a Container View with a controller of dynamic size inside a scrollview

Yup, there is. I managed to achieve that kind of behavior in one of my own projects.

All you gotta do is to tell the system that it should not add constraints that mimic the fixed frame set for your root view in Interface Builder. The best place to do this is in your container view controller when your embed segue is triggered:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// You might want to check if this is your embed segue here
// in case there are other segues triggered from this view controller.
segue.destinationViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
}

Important:

You gotta make sure that the view that you load into the container is constrained from top to bottom and you need to set the priority of one of the vertical constraints to a value lower than 1000. (It's a good practice to always use the bottom constraint for this.) This is necessary because otherwise Interface Builder will complain — with a good reason:

At design time your root view has a fixed size (height). Now if all your subviews have a fixed height and are connected with fixed constraints that all have the same priority it's impossible to fulfil all these requirements unless the height of your fixed root view coincidentally matches exactly the total height of your subviews and the vertical constraints. If you lower the priority of one of the constraints to 999 Interface Builder knows which constraint to break. At runtime however — when the translatesAutoresizingMaskIntoConstraints property is set as stated above — there is no fixed frame for your root view anymore and the system will use your 999 priority constraint instead.

Interface Builder Screenshot

How to make a container view size itself by the components inside it in storyboard

You can do this, but you need a little bit of code.

When a UIViewController is embedded in a container view, its "root view" has its .translatesAutoresizingMaskIntoConstraints set to true, and its frame is automatically set to the bounds of the container view.

If your embedded VC has constraints set to properly resize itself, you can disable .translatesAutoresizingMaskIntoConstraints on its root view when it is loaded.

As an example, suppose we have this layout, and the label in the "content VC" will have a variable number of lines:

Sample Image

We want the container view to automatically change its height so all the text will fit. But, if we add 10 lines of text, the "default" result will be:

Sample Image

So, we give the container view Top/Leading/Trailing constraints of 8 (so we have a little padding on the sides), and a Height constraint of 128... but we change the Priority of the Height constraint to 250 (Low). This satisfies IB, but gives us flexibility for its height at run-time.

In our "content VC" we add a label and constrain it Top/Leading/Trailing/Bottom all to 8 (again, just for some padding) and, of course, Number of Lines set to 0.

Now, in our main VC, we implement prepare(for segue...) and disable .translatesAutoresizingMaskIntoConstraints on the embedded VC's root view:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)

if let childViewController = segue.destination as? MyContentViewController {
childViewController.view.translatesAutoresizingMaskIntoConstraints = false
}
}

Now, at run-time, the intrinsic height of our label will increase the height of its superview (the root view), and that will override the container view's Low Priority Height constant, resulting in:

Sample Image

Here is the complete code for both VCs:

import UIKit

class MyContentViewController: UIViewController {

@IBOutlet var theLabel: UILabel!

override func viewDidLoad() {
super.viewDidLoad()

// add 10 lines of text to the label
theLabel.text = (1...10).map({ "Line \($0)" }).joined(separator: "\n")

}

}

class ContainerContentViewController: UIViewController {

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)

if let childViewController = segue.destination as? MyContentViewController {
childViewController.view.translatesAutoresizingMaskIntoConstraints = false
}
}

}

Setting the content size of a view inside UIScrollView

I set the constraints for you here.

Explanation:
You are getting ambigous content size because your scrollView does not know its content (white view's) width and height.

I added top,width and height constraint to white view. This way your scrollView knows its content width and will scroll only vertically. As for content height - u can change heightContstrait's constant in code, or completely remove height constraint if you use autolayout properly for white view's subviews.

IOS Swift Tableview controller embedded inside container view is not scrolling to the bottom of the tableview list items

this might help you, I have had same issue before, the problem your having is all about re-arranging the height of tableview to fit into containerview one, so update the height of the tableview view controller into the frame height of container view, like this:

tableViewController.view.frame.size.height = containerView.frame.size.height

you can also change the width to fit it also as your requirement,

this way i solved my issue.



Related Topics



Leave a reply



Submit