In my UIViewController I put a UIScrollView and attached constraints:
Then I added a view to this scroll view with following constraints:
and positioned it like this:
so as you can see it is quite long. When I run the app I can scroll it just for couple pixels instead of completely to the top of the screen. I want to make it possible to scroll it to the top so that it can cover everything what's under it. So what am I doing wrong here?
========= EDIT
for clarification - I want to achieve an effect that when user opens this screen, 10% of the screen is covered by the view. User can slide up this view and then it covers 90% of the view. And he can slide it down back to the 10%. Can you help me with adjusting constraints so that it looks good on every screen size?
Take a UIView inside the UIScrollView.
Set the constraint for scroll view as leading, trailing, top, bottom.
Select UIViewController in the story board and click size inspector then choose freeform then set the view height as bigger.
Then set constraint of UIView is leading , trailing , top , bottom as 0, so that the UIView will be same as ScrollView region. Now set height constraint something bigger so that you can design image view, label 1 and label 2. Then set constraint like the image view : top to UIView, leading , trailing and height.
For label 1: leading, trailing , vertical to UIImageView, height.
For label 2: leading, trailing , vertical to label 1, height and bottom to UIView (Important as based on this content view will be set).
After setting constraint You can select UIViewControl from story board and set the SizeInspector as fixed as it was before.
It will show the screen as you need (Image view, below label 1 and on scrolling label 2)
I have tested it in my demo project.
Hope it helps
Related
I am a little stuck with the ScrollView in Swift and Xcode 11.
My goal is a simple ScrollView with Labels and Textfields. Each label describes what the textfields are used for. For example there is a Label "Name", so you have to enter your name in the textfield under the label. For this I need a ScrollView because the App I am coding requires a few more information. When I am trying to put this in a ScrollView I am constantly getting the following error:
"Scrollable content size is ambiguous to ScrollView".
In order to find help I searched the internet and for example found this question: UIScrollView Scrollable Content Size Ambiguity.
Unfortunatly it didn't solve my problem. So I decided to create a small test project with the following:
- I created a project as a Single View Application
- I added a ScrollView to the ViewController
- I clicked on the constrains-Button at the canvas
- I selected 0,0,0,0 for leading/top/trailing/bottom.
- I clicked on "add 4 Constrains
- Now the warning appeared. Also the ScrollView was not resized to the ViewController... I don't know why.
- I added a UIView inside the ScrollView and set the same constrains, this time according to the ScrollView.
- The UIView (Content view) got an extra constrain: Equal width with the root view
- Now I added two Buttons, one with the text "Hello" and the other one with "world" on it.
- The "hello"-Button received the following constrains: 16 to leading, trailing and top, as well as a fixed height of 30.
- The "world"-Button got the following constrains: 16 to bottom, leading, trailing and over a 1000 so you can scroll through the ScrollView.
After all these steps the error is still there and if I run the app the "hello"-Button is at the top of the screen and the "world"-Button is at the bottom and I can't scroll.
Can maybe anyone help me fixing this issue. I am looking forward to every answer! Thank you for your help in advance!
Here is the trick that worked for me:
Add a ScrollView to your wished ViewController.
Select it in the Outline and open its size inspector.
Uncheck there the option "Content Layout Guides".
Now set leading/top/trailing and bottom constrains to 0 of the ScrollView.
Add in a UIView and constrain its leading/top/trailing and bottom also to 0.
Add an equal width constrain to the UIView. (The width needs to be equal the width of the view from the ViewController, with this way you are disabeling horizontal scrolling).
The warning will disappear if every element inside the UIView is chained vertically. This means, that the top element has a constrain to the top of the view and to the element under it and so on. The last element needs a constrain to the bottom of the view.
If you followed this steps you should be fine with ScrollViews. This way you also can add as many content as you want to the bottom and the ScrollView will extend dynamically.
I hope I explained it well enough.
It sounds like you're on the right track, and really close.
The first part is absolutely right - you add your ScrollView and pin it to zero for the top, trailing, bottom, and leading constraints. That makes it take up your whole screen.
Then you drop a plain old UIView into the ScrollView, and pin its top, trailing, bottom, and leading constraints to the ScrollView (all as zero again). Then you set the UIView to have an equal width to the ScrollView. The last thing is to set the UIView's height as equal to the ScrollView's height, but you change one thing: you set the priority of this constraint to be low (250). That's basically what allows the UIView to exceed the size of the ScrollView, so you can then scroll.
All you do then is add your buttons, etc inside the UIView, so you place them in relation to it rather than the ScrollView, and pin or align them as you wish.
Add a total of 9 constraints
1 - 4: ScrollView to Superview (leading, top, trailing & bottom)
5 - 8: Content view to Content Layout guide (leading, top, trailing & bottom)
9: Content view Width equals width to Frame Layout Guide.
But when you do this (right-click drag and drop) 7 & 8 constrains (trailing & bottom constrains to Content Layout guide) will have constant values. (check image below).
Just make them zero. Now it worked.
I have a 4 labels in a storyboard, one large one at the top, and 3 smaller ones, with the bottom one centered in the middle(horizontally and vertically) like so:
I have a few constraints set already, like locking the top label at the top of the screen, and centering the bottom. However, I do not know constraints I should use so that all four labels are equally spaced, AND the bottom label remains at the center. I have played around with some constraints such as the spacing between the labels, but when I try to view this using a different screen size, everything is messed up:
Any ideas?
The best approach is a UIStackView with axis-> vertical , distribution -> fillEqually , so hook it's top ,leading , trailing to main view , drag the 4 labels inside it , and ctrl drag from the bottom most label to main view and select center vertically && horizontally
You can made a trick here:
Set the top global label top constriants and center horizontally to super view.
Set the bottom label constraints center vertical and horizontally to super view.
Take three dummy view between label one-two, two-three, three-four.
Set constraints between these dummy view as equal height.
Then set top-bottom contraints between label and dummy view properly.
Set horizontal constraints of the label and dummy view. I have set as center horizontally.
Here I have attached the image:
For better understanding I have colored the dummy view as light-gray. You can set it as clear.
I am trying to layout my detail screen in IB with a tab bar and nav bar. However, there are three issues with the display when the simulator runs:
There is a gap at the top of the screen,
The dynamic label content extends past their container views at the bottom
The scrollbar doesn't reach to the bottom of the content.
Screenshot of simulator displaying the issues described
My question is how should I set my constraints so that the above issues are resolved?
I have a lot of constraints and I'm not sure where I'm going wrong or what would be the best way to present the steps I've taken so far. But here is a screenshot of my constraints and here is a summary of the constraints/steps I've taken so far:
Main view contains just one child: The Scroll View. Scroll view is pinned to top, leading, trailing of main view and bottom is pinned to the Bottom Layout Guide.top,
Scroll view has just 1 child subview ("Content View"). Content View is pinned to top + 64, leading, trailing, bottoms to Super View, and it has equal heights and widths to the Main view.
The content view has an image, Recipe Title subview, and Shadow Background subview. The Shadow Background subview contains another subview with some labels of dynamic height. I have constraints to pin the leading and trailing sides of these containers to the superview. And I have top, bottom, leading, trailing constraints to pin these subviews to the superview and/or eachother so that there is a chain from top to bottom.
The Shadow Background View contains the labels of dynamic height. The labels also have pin constraints of top, leading, trailing and bottom with the exception of the last label which does not have the bottom constraint.
I do not have any code that updates the layout-- everything so far is in the IB.
Any help is GREATLY appreciated!
Hallelujah! After spending a full frustrating week, I've finally found the magical formula in IB for laying out a scroll view + navbar + tab bar + dynamic label height.
My original problems were caused by the following mistakes:
Adjust Scroll View Insets should have been set to false
Content View Top and Bottom pins were incorrect
Missing some heights on some of the subviews
Last subview wasn't pinned correctly on the bottom
Maybe not all these steps are required and maybe this isn't the most perfect solution, but this is what worked for me. Here is a diagram of the solution for those that prefer pictures.
Main View -> Attributes Inspector -> Uncheck the Adjust Scroll View Insets checkbox.
Add Scroll View. This is the only child of the Main View. Pin Top, Leading, Trailing Space to the Main View. Pin the Bottom to the Bottom Layout Guide.
Add one subview (name it "Content View"). This is the only child of the Scroll View. Pin Top, Leading, Trailing Space to Scroll View. Pin Bottom to Scroll view with a constant of -49 to account for the tab bar. Also set its Height and Width to be equal to the Main View.
Add a child subview to the Content View. Top is pinned to Superview with a constant of 62 to account for the Nav Bar. Leading and Trailing is pinned to the Superview. The view also needs a Height-- give it either a fixed value or a minimum value if it is dynamic content (ex: Height >- 20). You may also need to give the Height constraints a lower priority such as 250.
Continue adding sibling subviews as needed. Pin the tops to the previous sibling subview. Pin the Leading and Trailing to the Superview. The last sibling subview should be pinned to the Superview. Each subview needs a height. There needs to be one continuous chain of constraints (Top & Bottom pins, Height) from the top subview through to the bottom in order to avoid that "Scroll View has ambiguous scrollable content height" warning and have the scroll work correctly.
Do a happy dance.
Hope this helps someone else.
Make the content view's top constraint have a constant of 0, not 64. For the label extending beyond the bottom of the container view, you'll have to post more information about the layout for us to help.
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.
I've created a simple view setup in interface builder. Here's how it looks:
The view hierarchy is simply:
view
- scrollView
-- label
The scroll view is shown with grey background anchored to its super view top, leading, trailing, and bottom with constraints of 0.
The label is shown with yellow background and has constraints as shown. Additionally, the label has content hugging priority of 1000 for both horizontal and vertical, and it has content compression resistance priority of 1000 for both horizontal and vertical.
In portrait orientation, the label is sized correctly:
In landscape orientation, however, the label is not sized correctly horizontally (I intended for the label to fill the width of the screen, less constraint insets as shown):
How can I get this label to size correctly horizontally in landscape orientation?
There is one solution for you.
1. Add your UIScrollView to container (UIView) with zero constraints:
2. Add constraints for Label: top, bottom, leading, trailing spaces = 20.
3. Add constraint: label.width = container.width - 40
For this, select label in the view structure tree, tap ctrl and pull
to container. And select Equal Widths.
Then select the created constraint and go to its Utilities and set
the constant value to 40.
You should get the following components:
Run the app, go to landscape and it works!
Hope it is clear. Best Regards.
It's hard to tell which constraint(s) to add/remove in order to get what you want because iOS reserve the right to adjust your constraints whenever it becomes impossible for it to satisfy all your constraints.
I make a blank project with the same view you have (UILabel as subview of UIScrollView) and make some constraints to get the UILabel resized properly on landscape.
A must check though:
Make sure you set the vertical/horizontal spacing constraints from the pin option, as shown below and try to remove unneeded constraints manually.