How to create a View that height depends on child views? - ios

This is the same as asking how to achieve wrap_content in iOS.
However, I found no suitable solution. Almost all solutions suggest to override intrinsicContentSize(). What if the view does not know any information about its child's height?
The case is like this:
I want to create a BaseDialogViewController that is responsible for blurring the background and displaying a dialog container. Then if I want to implement a dialog, I will extends BaseDialogViewController and add the dialog content to the container view.
So, the container needs to adjust its height according to the total height of the content inside of it.
How do I achieve this?

Just set constraints for all borders from the child view to the container view. You should ensure that the child view can compute its size from its contained elements, by setting constrains for all borders to its child elements, and so on.
The container view should only have additional constraints for its position (e. g. centering in its parent view).
The rest is done by Autolayout. It will calculate the size from the innermost elements with fixed or intrinsic sizes (e.g. labels, text fields, buttons) to the outer elements.

I realized that if child views height is specified, or has an intrinsic height,
you can set constraint from parent's bottom to child's bottom, and by setting this, the parent's height will be able to vary according to the bottom position of child's view.
I found this out from this answer.

Related

How do I auto increase the parent view size

I have a parent view which has so many child views most of the child views size are fixed except three labels.
so these three labels height can differ according to its content.
I want to change the parent view height when these label height changes and I want to change the position of other views whose that follows the label.
I think when I assign the label some contetn I should read its frame and get the height and I should change the postiion of following element according to that and I should change the parent view height according to that.
I want to do this the right way
Please let me knwo the right way to do this
Update:
what I'm trying to achieve is kinda like below image and it has so many fields like this

Why are my autolayout constraints conflicting?

I have an app using scroll view on a page with numerous icons within that scroll view. I don't understand auto layout very well, but I have constrained every single icon to its current canvas value to the view (after measuring and placing each icon in the correct spot). Why are there still conflicts (188 to be precise) and unambiguous positions?
As an example of what I have done in case the above is not clear, I have placed an icon in the top left of the scroll view. I have then constrained that icon on top, bottom, left and right of its current canvas value from the view.
This extremely hard to explain without showing (as in "live-demonstrating"), but I'll give it a try:
Autolayout for Scrollviews works differently than you probably think. You can't simply specify where to place its contents in relation to its bounds like that. After all, the "canvas" of the scroll view determines its size from the content you scroll over, whereas the size of the actual scroll view (lets call it its viewport, or "window onto the canvas") is determined in a different way (for example by constraining it to the elements around it).
This the opposite of how autolayout works for other views, since they are usually constrained by the size of their parent (up to the top view of a view controller and/or the screen bounds).
What you want to do is add all your items in a single view. From the smallest known size, constrain them to one another. Finally their container has a size resulting from its contents, i.e. your items. This is then the size of the "canvas" of the scroll view, so add it and constrain its position somehow (for example centering it horizontally and vertically). Now, the actual size of the scroll view and its position should be constrained by elements surrounding it.
It might take some thinking and training, so maybe you will want to test around in a small training project that only has a limited number of views to figure it out.
Add scroll view on the screen with constraints to parent view
Add content inside of scroll view
Put constraints between added view and parent view (NOT SCROLL VIEW)

How to add elements to ScrollView if the designer is too small?

I have a ViewController which contains a ScrollView and I'm trying to make a form menu so I need multiple labels and text fields.
I've been using the designer to do that.
The ScrollView will allow the user to scroll vertically, I already have many elements in the View but I need to add more.
The problem is that the size of the parent ViewController have a fixed size in the designer and because of that I reached the situation where I need to add elements under a label but there is just no space in the designer where I can put it.
hmmm.. not sure how this will carry over to tamarin/visual-studio, but in Xcode Interface Builder you can set the View Controller Simulated Size to "Freeform" --- and then set it as tall as you wish. Well, it may have a limit, but I just tested it and made it as tall as 5,000 pts. After laying everything out, you can set it back to "normal" size. At runtime, it will size itself however you've set the constraints.
Other alternatives...
Design your elements in "containing" views, and then add them in either dynamically via code or by manually setting the positions in the designer.
Use a single, tall "containing" view in your Scroll View. Make that view, say, 1500 its tall. In the designer, add the first few elements, then set the Y position of that view to a negative number. If your Scroll View is 500 its tall, set the Y position of the containing view to -400. The view will "slide up" in the Scroll View, and you can continue adding elements.

How do I prepare a UIViewController's view for being added to a UIStackView?

This is what I'm trying to do...
I have one view controller that needs to dynamically display different subviews based on the presence of some data.
Here is a simple mockup. Each colored block represents a unique subview.
Sometimes the green block needs to be at the top, sometimes the green block won't display at all, sometimes the light blue block will be something different, etc.
Each subview has interactive elements, so I've been creating and adding them like so:
Defining a new view controller
Defining its view
Calling addChildViewController and didMoveToParentViewController
Calling addSubview on myNewViewController.view
Using SnapKit to make auto layout constraints to position the view
I want to transition to UIStackView because it seems a good support system for this view because all I need to do is stack its subviews. I'm seeing many conflicting constraint errors and unexpected view frames when trying to add subviews with their own inner auto layout constraints.
Question
Am I setting myself up for failure here by embedding the views of 4-6 view controllers in the view of one view controller?
Also, how do I give the added views properties like minimum heights or content sizes without seeing many breaking constraints with UIStackView? (So they can stack, but one of them is say, 400 tall, and the other is 200 tall)
Answer
You can absolutely do this using UIContainerViews combined with UIStackViews and UIScrollViews, it's a complicated setup so here's a starter project to get you started:
https://github.com/Rnorback/ScrollingStackView
Here's what that project looks like:
You want the containers to have different sizes. In order to do that, simply add height constraints to the containers with Autolayout. If you want to change the height of the scrolling. Then you'll need to change the height constraint of the UIStackView.
Brief Explanation
When creating this setup, you have to make sure the UIStackView distribution setting stays in fill. That way you can set height constraints on UIContainerViews.
When setting up anything in a UIScrollView you have to make sure that the object is pinned to the edges of the scroll view and has a defined width and height, otherwise the scrollview will throw a constriant error. I think of it like the scrollview tries to press in on all sides of your content view and if any side gives, the scrollview won't be able to present it properly.
Hope this helps.

XCode: laying out scrolling content in IB

TL;DR: What's the best way to layout over-sized scroll-view content in Interface Builder?
I am trying to figure out the least painful way to layout offscreen / scrolling content in Interface Builder. My current approach has been to tweak scrollview content width and height constraints to see all content in IB, before reverting to proper contraints for building, but this gets to be a hassle. That said, I would prefer to do more more graphically, and less programmatically for general ease of editing.
The general approaches that I can think of are:
use embedded segues to build up views in a size-accurate fashion (the most intuitive, flow-charty approach)
tweak constraints for editing, reset for building
use placeholder values / constraints in IB (haven't tried this yet)
layout over-sized content programmatically
In more detail, I am trying to build a vertically scrolling view comprised of sub views. Each sub view is self contained and can potentially appear in more than one context and I would like to keep them isolated (in fact, I am embedding them as well, but that does not affect the question). What I would like to do, is use IB to layout a tall composite content view. I would then like to create the outer scroll view with a single content view again of a container view, embedding the composite content view. Ie. the grey content view on the left embeds the taller red / blue content on the right, and I am wondering if I can deduce the height, so it could be device agnostic (the views are square, so they will take their width from the device)
So summarized, is there anyway that I could derive the hosting scrollview's contentView height from the actual height of the content of the embedded view, or should I instead use approaches 2, 3, or other?
To be clear, Auto Layout requires that scroll view content views define constraints for the edges, and width / height dimensions. In my case, I would like to be able to preset the width to the device width, but leave the height to be derived from the red/blue content view. IB won't let me drag constraints between the embedding and embedded scenes in Storyboard, and when I leave the field missing, it uses the prototype values for the content height.
Is it recommended to use placeholder sizes (3) in IB to make the content visible for editing, knowing that run-time constraints will render it properly (ie over-size scroll views in Storyboard so all scrolling content is visible)? Conversely, is it foolish to even try - should I do all scroll-view content composition programmatically (4)?
Thanks in advance.
Edit:
Placeholder constraints allow you to get by, but force you to change the priority of the run-time constraints, and trigger IB / layout errors and warnings for conflicting constraints, despite selecting the placeholder checkbox on conflicting design-time-only constraints.
Use a UITableviewController with static cells. The cells will be your content views.
You can scroll the tableview down in IB to see the cells at the bottom and you get a nice extra behaviour like scrolling the views to the correct position when the keyboard is opened so it doesn't hide the textfield you clicked on.
And you don't have to worry about the scroll view at all.
If you want to reuse your content views you can make the table dynamic of course and provide the content views by code.

Resources