Scroll views + Auto Layout in XIB: ambiguous scrollable content width - ios

I have the following, simple layout: just a scroll view, with some views in it (please excuse the preview screenshot, since I'm using XIBs, there is no way to zoom out):
Here is my view hierarchy + constraints (the vertical constraints are all set up, throughout the view):
My problem with this case is that I get the following error in Interface Builder:
I've read up on the issue, I've found that I would need to add my scroll view as a subview to a simple view to silence this warning, but couldn't make it work (the view didn't scroll for some reason).
I think I understand the error here: the scroll view doesn't know, how far it can scroll horizontally, but I've found no way to specify this in IB (instead of setting it to a concrete value - which I don't want).
The problem is even more obvious, when I try to add another view to my hiearachy, and constrain its leading, trailing, and bottom edges to the scroll view:
The view just can't figure out its width, thus the messed up scrolling.
My question is the following: is there a good way to get rid of this ambiguity? In Storyboards, you can just add equal height/width constraints to the root view, but this is not an option with XIBs.

Okay, so I've managed to solve the issue with the following steps:
Use the following hierarchy: View of the xib ("main view") -> Additional view ("root view") -> Scroll view -> Additional view ("content view")
Pin the root view's edges to the main view so the screen is filled. Do the same for the scroll view (pin its edges to the root view's).
Define an "Equal Widths" constraint between the root view, and the content view. It's important to only constrain the width. My mistake was to also constraint the height, which caused the scroll view not to scroll.
Add any child views to the content view. Important note: you have to define the proper vertical constraints between the children, otherwise, the content view's height will be zero.
And that should be it! No more errors, and definitely no awkward scrolling glitches.

Related

Not able to add scroll view to the existing view

I am trying out the scroll view in my learning iOS. I added one main view, in that i added few sub views. Then i embedded that main view to scroll view. I also tried to set content off set value in my view did load. But scroll view is not scrolling.
Then i added through programmatically, but my main view was not coming in center. Still i can move my main view. Which i dont want. I want my view to scroll , i dont want any scale or move left or right.
Here is my code : Link
Any solution or help would be great. Not sure why i was not able to do. I can do with table view or collection view. But i want to do in my main view.
Thanks
I have found multiple issues in your codes and I have done some tweaking and the scroll view is working perfectly. Okay, let's talk what I did :
I did it through storyboard so,
I commented your code in viewDidLoad.
In main.storyboard, I added the scrollview just below your header view and gave a constraint 0,0,0,0 (top, leading, trailing and bottom)
Now I dragged your main view inside the scrollview and gave a constraint 0,0,0,0 (top, leading, trailing and bottom) and equal width constraint to the scrollview.
I added vertical stackview with distribution fill inside the mainview and gave a constraint 0,0,0,0 (top, leading, trailing and bottom)
Check if this is working or not!
There is some issue with the constraints of the scrollview in your application because of that your scrollview is not scrolling. To add scrollview properly to the exiting view you should follow this link:-
Add a ScrollView to existing View
Or if you want it for specifically for swift 5 then follow this link:-
How to add Scroll View in Swift 5?

iOS UIScrollView, what am I misunderstanding? I cannot get a scrollview to scroll

I am a pretty new iOS developer and am coming across my first need for a scroll view. The page I need to design is a little complex. Since I was struggling to get that to layout correctly, I decided to create a super simple scene just so I could make sure I understood how to get UIScrollViews to work. Apparently it didn't help as things aren't working and I am stuck after following several tutorials.
I'm working in Xcode 8.1 and Swift 3.
Screenshots at the end of this post.
I have a scene that consists of a scrollview and a child view with two labels in it. I’ve set the labels to be ~700pt apart to try to make scrolling happen. Nothing scrolls and you can only see the first label. Additionally, the child view does not expand to be full height.
You can see in the screen shots that my scroll view has constraints to pin it to the sides of the superview.
The child view has the same.
The label constraints position them within the child view and 700pt from each other. I thought that this would give the views the height they need to make scrolling happen. There are no constraint errors.
I am hoping for the red childview to fill the vertical space and then scroll. At this point I’d take any layout as long as something was scrolling. Nothing is though, what do I not get?
Screenshots:
(removed due to link limit because I'm still a new SO user)
EDIT (6/12/16):
I've made some changes and gotten a little closer. Primarily, it was suggested to me elsewhere to set one of the labels to be equal height with the scroll view. This now gives me the "bounce" effect which means stuff is sort of scrolling; however, we're still only dealing with one screen of content as the second label which is hidden below is clipped off.
Here's where things stand:
edited hierarchy
edited screenshot
When you are using a UIScrollView in a storyboard, you need to ensure that the scroll view is able to compute the size of its content. If you don't have sufficient constraints then you will get an error in Interface Builder:
Scrollable Content Size Ambiguity
Clicking the Info icon on this error will advise you that there needs to be constraints touching all sides of the scroll view and to ensure that you can trace a continual line of constraints from left-to-right and top-to-bottom.
You can achieve this with or without the content view you have added. I will show you how to do it without the content view in scroll view, simply because there are fewer constraints that way and therefore less typing.
Add the scroll view to the root view
Constrain the top/left/top/bottom of the scroll view to its superview (the root view). Remember to turn off constrain to margins if you want the full width of the screen
Add label 1 and label 2 to the scroll view
Constrain top/leading/bottom of label 1 to the scroll view
Constrain top/trailing/bottom of label 2 to the scroll view
Constrain the trailing edge of label 1 to the leading edge of label 2 with 0 space
Constrain label 1 width to be equal to the width of the scroll view
Constrain label 1 height to be equal to the height of the scroll view
Constrain the width and height of label 2 to be equal to the width and height of label 1
There is no step 10 :)
ScrollViews are particular in that they like to know explicitly how much they are supposed to scroll. The best way I have found to handle this is to have the following hierarchy with some constraints:
-Scroll View
-Content View
-View (constrained to top, bottom, leading, trailing anchors)
-Your other views (e.g. Label)
By having one View living underneath the Content View and then containing all of your other Views within that View, the ScrollView then knows how much it's supposed to scroll (it just uses the size of the one child View) no matter how much stuff you have inside of the child View.
Let me see if I can snap a picture of an example from one of my projects. In the meantime, give this hierarchy a try and let me know if it works for you. You would probably constrain the Label to the top and leading anchors of the child View and then constrain the height to something taller than the screen (e.g. 1000 units).
Let me know if you have any questions.
Edit: Example hierarchy below

Xcode Scroll View Auto Layout Issue when Embedding with Navigation Controller?

I seem to be having issues when it comes to embedding a scrollview within a navigation controller. So here are the steps I take, and its really easy to replicate the weird error i seem to be getting.
1.) Drag and drop a UIViewController
2.) Followed by a UIScrollView
add constraints to UIScrollView, 0 on all sides, uncheck constrains to margins.
3.) Drag and drop another View into UIScrollView
add constraints to UIScrollView, 0 on all sides, uncheck constrains to margins.
Control drag from view into scroll view, make same width and height
After the following steps you will see in the following images that the view is not following the constraints I set, for some reason it thinks 0 is +64 from the top of scroll view? Not sure what I'm doing wrong here as it is very annoying visually.
In your view controller's attributes inspector, look for the Adjust Scroll View Insets and Extend Edges Under [Top|Bottom] Bar options.

Setting UIScrollView Width

I have a UIScrollView added to my ViewController. And a View on top of that Scrollview. I have done the following:
Placed scroll view inside my original View and set top, left, right, and bottom constraints. Unchecking Constrain to margins.
Added a UIView within the scrollView (to hold my labels and such) and added the top, left, right, and bottom constraints, constrain to margins unchecked. And set equal widths to the original View
I then add an image view and three labels inside the view placed within the scroll view. And add top, left, right, bottom, and height constraints for them.
The scroll view works and my view does scroll and my labels and image view are centered but everything is very wide.
I am wondering how I make it so the View is not wide and I cannot scroll horizontally, only vertically.
Add an equal-widths constraint between the view inside the scroll view, and the root-level view of the view controller.
I just recently figured this out. Try doing this:
Make a scroll view
Put all of your labels and buttons into a stack view (If you don't know about stack views, check this out: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIStackView_Class_Reference/
Constrain the stack view's width and make sure the Allignment and Distribution are set to fill
Put the Stack View inside of the scroll view
Constrain the Scroll view to your hearts desire
Putting the labels and what you want in the scroll view should help with the width boundaries. Here's a picture of my successful scroll view. Hope this helps :)
In short, the contentsize is no effect while you use autolayout.
if you want you scrollview can scroll, uou should add a container inside scrollview and add origin subviews to the container.
For example, use snapkit (maybe some typos here):
you have a scrollview.set it's equal self.view's frame by autolayout
[import]then you add a containerView as scrollview's subview. set contraints:
make.edges.equalTo(scrollview) // mean its frame equal to scrollview
make.width.equalTo(self.view) // set width equal to self.view
make.height.equalTo(yourheight).priorityLow() // the actual height,if no changes,you can ingore .priorityLow()
add your sunviews to containerView,add the contraints must set to containerView,can't set to scrollview's.forexample,:
containerView.addSubView(myview)
myview.snp_makeConstraints { (make) -> Void in
make.left.equalTo(self.containerView)
make.top.equalTo(self.containerView)
make.right.equalTo(self.containerView)
make.height.equalTo(267)
}
Read this official doc -
Technical Note TN2154 UIScrollView And Autolayout.

How to use ScrollView and ContainerView with Autolayout checked

I have trouble implementing scrollview with auto layout:/
Here is simple "Hello World" project with that problem: http://www.sendspace.com/file/cg96by
But the problem… I need to create scrollview, but also I need to use auto layout. So I created pure single view application, added (like I saw in some tutorials) Scrollview (the same size as main view), added constraints (all zeros) and then add Container View (the same size as scroll view), add constraints and.. It's didn't work:/ It doesn't scroll. Here is the screen of that situation:
Now, when I delete two constraints named: Center X and Y Alignment (marked on the screen), it works perfectly, but Xcode5 doesn't quite like it :/ and shows some errors like on the next screen below.
Why does he want width and heigh 0 ?!
Actually ContainerView doesn't matter. I've also tried with image view. When you select "Add missing constraints" it also add Center X and Y Alignment. And scroll doesn't work. When you delete them, scroll works but you have this warring:
Ok, I find manually adding the autolayout constraints to be quite confusing, using the "Add New Constraints" button at the bottom really comes in handy, try this, after you get each view where you want it use that way of adding layout constraints for each view (ie scrollView, containerView, UIImageView) I did this, and heres the example, select each constraint as I have so that the top, left, bottom, and right edges are set, this should do exactly what you want.
You will probably want to erase all your current constraints and then implement them this way.
heres the layout like you want http://cl.ly/image/463k2043401L
and heres the example adding the constraints: http://cl.ly/image/472l2V0l3N1L
To keep it dynamic so that you can rotate it, you will want to do the above for all view BUT the container view... then If you control drag from container to scrollview with no constraints, you can add all of them that it suggests except for the height and width at the bottom, that satisfies any missing constraints and should do the trick, It will center the container inside of the scrollview and keep it pinned to the top, bottom, left and right, and it should dynamically change with your scrollview content size.
http://cl.ly/image/1o3k1e452W0g
Sorry for the confusion, hope this helps!
I had a similar problem and i found relative simple solution from within Interface Builder using pure Autolayout without any code.
For proof-of-concept at first remove any constraint in View Controller to if see this works.
This is sample layout:
View (main view of my UIViewController)
Scroll View (UIScrollView)
Container View (UIView)
Content View (e.g. UIImageView)
A. Scroll View width/height should be smaller that Container View width/height
B. Container View should have some determinated width/height (may be explicit width/height )
C. Do Control-drag Container View to Scroll View and add only:
Leading Space to Container
Trailing Space to Container
D. Check out those two constraints and set "constant" value for both to 0
E. Run app and

Resources