UIScrollView Autolayout height not setting on dynamic content - ios

I have two labels that are inside a stack view that is encapsulated in a scroll view. The layout structure is like the following:
The layout looks like so in the interface builder. (This is the view with the contentView selected)
The Content Stack View is pinned to the contentView's via top, leading, trailing with 8pt on each.
The labels are set at runtime and can be quite tall. This cuts off the text and causes the scroll view to not be scrollable. (Cuts off at bottom)
I've went through a few other similar questions on here but was unable to find a solution to mine.
Some are resources I went through I looked at were Mokagio, and Natasha.
I have been on this for over a day now and am completely stumped.
How does the Scroll View's content size become scrollable from the generated content?

Please follow below steps:
Add UIView into UIScrollView and then add both UILabel into UIView.
Set top, bottom, leading, trailing constraints to UIScrollView and UIView
For both UILabel set top, leading, trailing, bottom, width, and height constraints.
lastly edit height constraints to set - priority High(750), select >= from constants dropdown for both UILabel
IMPORTANT: set UILabel's number of lines to 0
Please see below screenshot for UIlabel constraints:

Related

Reverse scrollview height controlled by stack view in storyboard

My Goal
To make a reverse scroll view that changes height with the height of the vertical stack (the contents of which will be controlled programatically)
What I have tried
Setting the stack view, Scroll view and content view the same heights. I am not sure how to change the simulated size of the view controller with it
Note: I am using Storyboard not swift UI, I have researched this and all I can find are tutorials for how to do this in SwiftUI
I wanted it to be controlled by the height of the stack view, so it does not scroll when there isn't anything to scroll to, if this is wrong please correct me and give me some guidance
The ViewController now:
Can anyone help?
If I understand your question correctly, I had a similar issue recently.
My solution was:
Fully constrain the UIScrollview within the superview
Place a UIView inside the UIScrollView. Align the UIView's leading and trailing constraints to the UIScrollView's content layout guide AND frame layout guide ( =0, or whatever margin you need). Align the UIView's top and bottom constraints to the UIScrollView's content layout guide ( =0 ). Constrain the UIView's height to be equal to the height of the UIScrollView's frame layout guide with a priority of 500 (make sure the multiplier is 1 as Autolayout might set it to something else). These constraints should be added by control dragging from the UIView to the UIScrollView's layout guides within the document outline (I had problems if I didn't add them this way). This fixes the widths, but if the UIView's height needs to expand then the equal height constraint can break allowing it to grow outside the UIScrollView's frame, triggering scrolling.
Place your UIStackView inside the UIView. Align the UIStackView leading and trailing constraints to the superview (the UIView), or use a horizontally centred within superview constraint. Constrain the UIStackView to be vertically centred within the superview (again, the UIView). Align the bottom constraint of the UIStackView to be >=0 relative to the superview (UIView). Thus, when the UIStackView is smaller than the UIView (and UIScrollView) it remains centred and doesn't scroll. As soon as the UIStackView (and UIView) exceeds the size of the UIScrollView, the >=0 constraint between UIStackView and UIView bottom takes precedence over the equal height constraint between the UIView and UIScrollView frame layout guide, forcing scrolling.
In step 3, I think you might be better served by aligning the top of the UIStackView to the top of the UIView, rather than having the UIStackView vertically centred. The bottom constraint should still be >=0. I didn't try this myself but it should still work.
If you need the UIScrollView itself to increase in size, then pin its top and bottom within the superview to the minimum size you want it to be, with a low priority such as 250, then add >= constraints to fix the outer limit of where you want it to be. For example, Constrain the bottom of the UIScrollView to be =100 from the bottom safe area guide with a priority of 250, then constrain it to also be >= 25 from the bottom safe area with the default priority of 1000. In this case the first constraint to break should be the bottom of the UIScrollView which will allow the UIScrollView to grow until it hits the bottom >=25 constraint, at which point the UIView to UIScrollView_frame_layout_guide equal height constraint will break triggering scrolling.
I hope that makes sense (and that I haven't missed anything)!
PS I also ran into a problem with the UIStackView contents (programatically defined in my case) resizing in odd ways which seemed to be fixed by changing content mode from "Scale to Fill" to "Redraw". I set distribution to "Fill Equally" or "Fill Proportionally" depending on the look I wanted (I had two such views).

UIScrollView height while adding content programmatically in UIStackView

I am trying to make a view containing an UIScrollView. This UIScrollView contains 3 UIViews. The last one contains another UIStackView I wanted to fill at runtime.
Here an image of the storyboard :
But when I add content at runtime in the second UIStackView, the ScrollView's height remains the same.
The second UIStackView is defined as the first one with:
Axis : vertical
Alignment : Fill
Distribution : Equal Spacing
Then I use :
mStackView.addArrangedSubview(matProgress)
The result below :
What's the way to have the bottom view and the ScrollView stretch to fit the content.
The layout can be done with auto-layout and constraints.
The key points are:
do not set height constraints on either StackView
set the "Main" StackView Distribution to Equal Spacing
set the "Main" StackView Leading, Trailing, Top and Bottom constraints to its Superview (which is the ScrollView)
you do need to also set a width constraint on the "Main" StackView to control the horizontal contentSize
The only quirk will be on startup. If you have NO content in the bottom / inner StackView, it will still "exist" in the Main StackView and take up space. There is a trick to get around that, but it must be done in code.
You can see a working example here: https://github.com/DonMag/StackyScrolly
If you have UIScrollView and the child views with auto-layout. Setting programmatically the height of the scrollview will stretch the inside views to comply with the auto-layout.
So, you get by code the height of the third view and set the UIScrollView height to view1.height + view2.height + expectedThirdViewHeight.

How do you set constraints for scrollview that doesn't occupy the whole parent view

I'm trying to build UI similar to that of ios photo gallery : Navigation view controller with a scrollview occupying 80% height and 100% width of the parent's view and the collection view controller occupying the rest of the height and 100% width. So here's how it looks like :
The blue area is scrollview and its content view. The bottom part is a collection view which suppose to behave like a carousel. You can see the constraints that I have set in the following screenshot :
:
I want to set the scrollview height so that it only occupies 80% of the parent view estate and the collection view occupies the rest. However, I can't seem to resolve scrollview constraint issues such as autolayout not able to resolve height/y position of scrollview. As you can see in the above pic, I tried setting the height of the scrollview to 50% of the parent view but the autolayout still complains about not being able to resolve height. If I let interface builder resolve the issue, it just adds spacing to the content view inside scrollview and pushes it down as a result. You can see that in the following screenshots.
Your view heirarchy is correctly setup so thats quite nice and you are on the right track of what constraints to add. I'm going to write all the constraints starting from step 1.
To your UIScrollView add a top, leading and trailing constraint to the superView. Also add a equal height constraint between your UIScrollView and the superView and set the multiplier to 0.8.
Now add your UICollectionView below the UIScrollView and give it a leading, trailing and bottom to the superView. Also add a vertical spacing between the UICollectionView and UIScrollView.
Now add for the contentView inside the UIScrollView. Add a leading, top, bottom and trailing for the contentView to UIScrollView. As soon as you do this, the constraints will break and Xcode will complain. Now what you need to do more is add a equal height and width constraint between the UIScrollView and contentView. Set the priority of this equal height constraint (assuming you want vertical scroll) to something like 250, so that it breaks when the content inside the UIScrollView becomes too large to be displayed completely.
Now as far as that extra spacing issue is concerned. What you need to do is, select the UIViewController that has your UIScrollVIew and then select the attributes inspector for this UIViewController and uncheck the adjust scroll view insets option. For a screenshot, check this.
As i see from above do the following.
Add leading, trailing and top constraint to scrollview.
Add height constraint i.e drag from scrollview to superview and add equal width, in equal width constraint change the multiple factor to 0.8.
Add leading trailing, bottom constraint to collection view with respect to superview and vertical space constraint with respect to scrollview.

Auto resize UIView based on multi line UILabel

Problem:
I have a custom view with a multi-line UILabel (se picture below).
This custom view is then added to a screen in my storyboard (se picture below).
This works great. The problem is that the multi-line label will change dynamically a few times under execution, and then the blue UIView box won't fit. It's also a problem with smaller/bigger screen size.
Question: So how do I get the UIView to automatically resize in height according to the height of the UILabel? Is it possible to do through Interface Builder and Autolayout? (not nececery, but most of my other settings are done through IB)
Let me know if there is more details needed.
As long as you make sure that labels in your custom view are pinned to all sides (Title Label pinned to: Leading, Top, Trailing of the superview and Bottom to Content Label; Content Label pinned to: Leading, Bottom, Trailing of the superview and Top to Title Label) you will have your superview change it's height according to the content.
Also, note that your superview won't need a height constraint, just pinning it to the Leading, Bottom and Trailing sides should be sufficient.
I had almost identical view in one of my apps. What I would do to make sure the height changes according to update is this:
customView.setNeedsLayout()
customView.layoutIfNeeded()
You can also wrap this code in UIView.animate(withDuration: ...) block
Cheers!

Using UIScrollView with Autolayout

I am trying to get a simple scroll view to work with autolayout. My SuperView has a Scroll View. Inside the Scroll View is a ContentView and then a ButtonsView.
View (320x480)
|
|__Scroll View(320x480)
|
|__ContentView(320x556)
|
|__ButtonsView(320x175)
The ScrollView constraints to the SuperView are 0,0,0,0 for Leading, Trailing, Bottom and Top. The ContentView constraints to the Scroll View are 0,0,-96,0 for Leading, Trailing, Bottom and Top. The -96 is because my content view height is 556. I have a ButtonsView inside the ContentView. The ButtonView constraints to the ContentView are 0,0,238,64.35 for Leading, Trailing, Top and Aspect Ratio.
I am getting Missing Constraints and Scrollable Content Size Ambiguity errors on my xib.
I do not want to to hardcode the width and height for either my ContentView or ButtonsView as I want the xib to work for iPad as well.
Can someone please tell me what I am doing wrong and how I can get this fixed?
Thanks
This is not a duplicate question. The question above has a scrollview which doesnt work as intended. My question is more about how autolayout rules can be applied to the scrollviews.
You should let the inner contents of your ScrollView to determine its content size. Whether by indicating fixed height and width (which you don't prefer). Or by putting constraints to determine the sizes of inner contents related to the View. So in your specific case, you can add an Equal Widths Constraint for ContentView and View. To adjust height, you can add an Equal Heights Constraint for ButtonsView and ContentView with multiplier of 175/556
You just need to add a Bottom constraint in your ButtonsView to the ContentView. With those constraints, now the ContentView can guess its height, and so the ScrollView, too.

Resources