Create custom view with constraints and initializing with frame - ios

I need to create a custom view like this (small view over current controller background) and load it programatically:
I used to create full-size custom views, and the problem I have now is that I'm not sure about how to handle frame vs constraints in smaller ones that depend also on the parent view controller.
I would need to set the frame of the view in its init(), so it has some margins in relation to the background frame, and it also needs to have a flexible height depending on the size of the text (so I can't use only a fixed frame, its size must depend on the text)
If I pass the frame in its init(), it doesn't respect the flexible height, and if I use translatesAutoresizingMaskIntoConstraints = false, it doesn't respect the position over the background view.
Is there any way to combine both?

Related

iOS incorrect frame size at runtime

I've got an UIImageView inside a root view of a controller, and I've set it to be 90% of the screen width and given it an aspect ratio as constraints to set the dimensions.
In the code I'm trying to do something with respect to the size of the UIImageView at runtime, however when I get the frame.size.height or frame.size.width of the UIImageView they are clearly wrong and way too small.
At first I was accessing the size in viewDidLoad(), after which I found quite a few posts suggesting to do it either in viewWillLayoutSubviews(), viewDidLayoutSubviews(), or viewWillAppear(). Unfortunately I've tried all of those and none of these contexts seem to provide the right value. I suspect it may have something to do with auto layout but I'm not quite sure how to get around this. Any insight as to why this may be would be appreciated
viewDidLoad is too early. At this time, the views have the frames they were given in the storyboard. Ditto for viewWillAppear.
In viewWillLayoutSubviews, the view controller's top-level view has its correct frame, but its descendants do not.
In viewDidLayoutSubviews, the view controller's immediate subviews have their correct frames, but more distant descendants (“grandchildren” and so forth) don't.
If the image view is a direct subview of the view controller's view, then its frame is up to date in viewDidLayoutSubviews.
If the image view is a more distant descendant, then there is no method you can override in the view controller that will be called after the image view's frame has been updated but before the image view is visible on screen. Here are two options in this case:
Create a custom subclass of UIView to be the superview of the image view. When the superview's layoutSubviews runs, after it calls super.layoutSubviews, the image view's frame is up to date.
Create a hidden UIView that is a direct subview of the view controller's top-level view. Use constraints to make this hidden view's frame exactly match the image view's frame. Hidden views participate in layout, so when viewDidLayoutSubviews is called, this hidden view's frame is up to date, and is the same as the image view's frame will eventually be (except that the hidden view's frame is in the top-level view's geometry, which might be different than the geometry of the image view's superview).

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

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.

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

View as a subview of UIStackView cannot be rotated

I have a UIStackView, in it there's a subView called A. I want to rotate the view A. But nothing happened. I can rotate the A's layer, it's OK. So how to make animation of subviews of UIStackView?
Once you add an "arranged subview" to a stack view, its frame is automatically managed by the constraints added implicitly by the stack view. While you could hypothetically add additional constraints which could be animated, there's no set of constraints that would allow you to accomplish a rotation.
One solution would be to nest another view inside the one that's being managed by the stack. You could then override layoutSubviews in the outer view to opt out of auto layout for the inner view, so you can manage its rotation. Whatever updates that you make there to the inner view's frame could then be placed inside an animation block.
EDIT:
According to the docs for the transform property of UIView, "In iOS 8.0 and later, the transform property does not affect Auto Layout. Auto layout calculates a view’s alignment rectangle based on its untransformed frame." That seems to imply that a rotation should work even in the presence of auto layout constraints. That said, my guess is that transforming the view is really just a convenience for transforming the underlying layer.

UIViews with ambiguous height

I have a collection view inside of a UIView. I need to have the collection view communicate to the UIView the height it should be depending on the amount of content inside the collection view.
I need to then let this UiView (white box) know how tall it should be. I believe I did this part correctly in my setup function, but I'm not certain (I'm new to coding).
I need to have the collection view communicate to the UIView the height it should be depending on the amount of content inside the collection view
That height is the layout's collectionViewContentSize height. But note that this height can grow beyond the size of the window, since this is a scroll view - the whole point is that the size of the content can be greater than the size of the collection view. Thus it might be better to ask yourself why you think you need to do this.

Resources