Disable Horizontal Scrolling of UIScrollView AutoLayout Resizable ScrollView - ios

I have a UIScrollView which is getting resized on runtime according to some conditions. Now i used auto layout properly without using a single constraint extra or less. The first subview of scroll view has leading, trailing, top, bottom and equal width to scroll view and the height of the content view is managed by its inner content which is also changing depending on the runtime condition. Now according to my constraints my content view should not scroll horizontally as i used equal width to scrollview. But its happening. Can anyone suggest what am doing wrong? Here is the images of constraints i have used.
NOTE:- I have seen the posts on stack where this kind of question answered but my case is different.

Content UIView width should be equal to the width of UIScrollView's superview for instance, not UIScrollView itself.

In my case, I used to 'constraint to margin' option while I am adding constraint from storyboard. When I only add trailing and leading without relative to margin problem solved. I did not give any superview to my UIScrollView.

Related

Why is there a big margin in my scrollview when it's all set to 0

I have scrollview with a stackview with all my contents. I set all my margins to 8px but for some reason, there is a big space to the right. Even if I change the margin to 0px.
Am I doing something wrong?
Is it maybe better to make a tableview and make a cell out of my stackview? Seems very unnecessary to do this. But I cant figure this out.
When you define constraints inside a scrollview, the content doesn’t bind to the scrollview but to the content insets (margins). With this you can install content that is wider than the scrollview and be able to scroll horizontally.
What that means is the content of your scrollview can’t deduce its width just by sticking constraints to the sides, you have to explicitly set a width constraint on a child view.
In your example, it will use the smallest width it can, which looks to be the width of your three checkboxes.
To fix that, add a width constraint to any child view, like your first text field, or better, on your text edit because it takes the whole width.
In addition to this, you should add a CenterHorizontally constraint on your text edit too and make your left constraint on "Equal or Greater" or else your content will be aligned to the left.
Here is the official documentation on ScrollView to see this in more detail.
The content inside the scrollView must be the width of the device. The scrollView will not adjust to that width by itself. First try to set "equal widths" constraint of the scroll view to the view controller. If that doesn't work, keep reading.
For this StoryBoard, what you must do is put a UIView inside the scrollView.
The scrollView must be equal widths and equal heights of the viewController. Then the UIView must be equal widths of the scrollView, and then set its top and bottom anchor to the top and bottom anchor of the scrollview.
Copy all your subviews into this UIView.

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).

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.

dynamic height of of scrollview subviews in autolayout ios

I am creating a UIScrollView from xib, in which 3 view are there 2 UIViews and in middle an UIImageView. when I am setting constraints Xcode asked to set Y position constrains. But the problem is Y position constraint is blocking Scrollview to scroll down and automatically adjusting the views which looks ugly in landscape mode.
when I am delete that constraint it ask to fix height of subview. I searched a lot but I am new in autolayout so not understanding many of solutions. any help would be great.
You have to set all the height constraints in the content view.
But you also want the height of the Content to be proportional to the screen size.
To do this assign the height constraint of the imageview [equal|proportional|a-computation-of] to the view containing the UISCrollView.
It seems weird to skip levels of herarchy when assigning constraints between two views whose are not direct ancestor/sibling of each other but within a scrollview (at least) it is perfectly acceptable.
You are basically telling the scrollview that it's content has a known size and at same time setting this content to adapt dinamically to the screen size (if the constraints of the root uiview are set correctly)
UIView1
|---UIScrollView
|---UIView2
|---UIImageView [heightConstr.constant=UIView1.height-UIView2.height-UIView3.height-margins]
|---UIView3
This is the basic idea, to be done programmatically, then you can explore other solutions.
Unfortunately the constraint system in ios pretty much sucks when it's up to more complex equations involving more views for a single constraint.
UIScrollViewcan be tricky when adding constraints. You should always add a subView that will behave as the content view for your UIScrollView and all your subsequent views will go inside this content view.
UIView1
|---UIScrollView
|---UIContentView
|---UIView2
|---UIImageView
Set your UIScrollViewconstraints as you would normally but set your content view to have leading, trailing, top and bottom to the UIScrollView but also add two more constraints which will be equal width and equal height to the viewController.view but will have a low priority (So that whichever direction your content will increase in, that constraint will break and automatically increase the content size of the scroll view by taking in the inferred height of the content view). Now go on and add constraints on all your subview as you normally would. Which i'm assuming would be:
Your topmost view will have top and leading and trailing to its superView and also a fixed height.
Your bottom view will have leading, trailing and bottom to its superView and also a fixed height.
Your UIImageViewwill have a leading, trailing and top to top most view and bottom to the bottom view.
Edit:
Here is the screenshot just in case (To show the view hierarchy with the content view's constraints in the inspector)

Detect a UIScrollView's height dynamically

I have a real problem with detecting UIScrollView height. I searched a lot and found this solution:
So I dragged from Content View to View and made Equal Height. But I does not work for me.
I also tried to calculate scrollView height according to elements height in it, but I do not think that it's a right way.
How can I set UIScrollView height dynamically? What is the correct way for doing it?
Your ScrollView should add a ContentView like this:
select your scrollView and in size Inspector bottom, set the width like this:
for more details on how to handle scrollView in Interface Builder your can check out this AppleDoc Working with Scroll Views
Hope this help you!
You only way to set height of your scrollView is by calculating the height of individual objects added to scrollview.
Programatically, calculate the height of each UI object and at the end set content height to scrollview.
[scView setContentSize:CGSizeMake(300, height)];
In above line, 'height' is nothing but a sum of all heights of all UI objects calculated.
By doing the below stuff's, I was able to implement UIScrollView with Automatic height based on the contents inside.
Add scrollview to the main view.
Add one ContentView inside this container scroll view.
Give proper constraints inside this content
view to the container scroll view as well as to its internal UI
Components. Please note that you should not give fixed height to the
content View. The constraints of the content view should grow
according to the UI Components inside
This might give you a layout
warning as 'Unambigous.... '. To fix this, give 'Equal Heights' constraint relation between content view and scroll view
Try the above steps, and this will solve your issue :)
Do you want to add item (UIView, UILabel...) in your UIScrollView by auto layout? If so, just put these in it and create correct constraints for them.
The key point is each item which in UIScrollView have top, leading, bottom and trailing side constraints to their superview. Most important is Make Sure that your UIScrollView has top, leading, bottom and trailing Descendant Constraints to its sub-items. It will calculate correct content height of scroll view for you.
In your solution, if your contentView has zero frame, it will not give you any height for scroll view.

Resources