Swift: UIScrollView doesn't scroll after the user edits the height of a UITextView - swift

I have two UITextView inside a UIScrollView and the TextView can resize as the user types more text into them. I need the page to be scrollable to account for this so I put them in a ScrollView, however the height of the ContentView doesn't change with the TextViews. Here's what I tried so far:
adding a bottom constraint from the last helper text to the bottom of
the content view with priority 1000 and constant 210. This doesn't
work because the section will be scrollable before the TextViews get
taller and on tablets or larger devices it will make my first
TextView taller.
adding a bottom constraint with a constant of 210 or lower will give me a layout error.
I also thought about calculating the height of the content view and maybe adjusting the constraint based on that but this doesn't work either.
Here is a link to the file in question: https://www.dropbox.com/s/g7q1lbj0pxx14jh/Main.storyboard?dl=0
Any suggestions?
It's also worth noting that the keyboard will cover the second TextView when the first one gets too big so I will eventually need to edit that constraint based on the height of the first TextView (to give it more padding at the bottom so that the user can bring the second TextView in view.

Here is the fixed variant https://www.dropbox.com/s/gujry7ngziaipm7/Main.storyboard?dl=0
I found just 1 error:
You forgot to specify bottom offset from last view in View Container which is UILabel - "Being clear...", so your view container doesn't know when to resize as soon as you do not specified all offsets to it.

Related

What am I doing wrong with this Scrollview?

I am attempting to set up a scroll view and every video I watch they say the same things:
•Make scrollview in VC
•Make it bound to all margins (0,0,0,0)
•Embed a content view inside of Scrollview
•Content view margins are (0,0,0,0)
•Set Equal heights & width from content view to superview
•set priority of height to 250
I have done this time and time again and cannot figure out why it still isn't working. Can someone please double check these screenshots?
Try adding some subviews into your content view and make sure to have a complete set of vertical constraints from top to bottom.
If you go in the Size inspector under the "Scroll View" Section you can find the "Content Layout Guides" tick, disable and the errors will disappear
If you Set All the constraints to ScrollView and want to set its contents in code .. it remains complaining about its constraints because they remain ambiguous .. so to remove error from story board
what you do is set Ambiguity to never verify and error will go away .... hope it will help
Looks like you do not have anything bound to your Content Layout Guide.
So basically you have two guides in Scroll View: Frame and Content.
Frame Layout Guide provides you the ability to bind to your UIScrollView's frame. E.g. equal width between your Content view and Scroll View itself.
The most useful here is Content Layout Guide. Basically it helps to determine the scrollable content size of your UIScrollView's contents.
So in your case you have to have a Content view inside your Scroll View that has equal width with Frame Layout Guide and have its edges pinned to Content Layout Guide. Like so:
Oh, and do not forget to have your Content view have a determined height so your scroll view will calculate the size of its scrollable contents.

UIScrollView Controller not scrolling fully

I am pretty sure this has something to do with the dreaded AutoLayout. (been trying since 2days to get hang of it)
So I mastered it somewhat, but now I have problem where my UIScrollView is not scrolling fully down, pictures are much better at explaining these things
this is the scroll view
this is the content view
so the problem is the scrolling is happening but then again it springs back up. So I am not able to click on the signup button
EDIt 1
Edit:
I have created a little example on github for you to look at, here. The project illustrates the answer below and uses the techniques I describe and nothing else.
Original Answer:
couple of things I would advise here.
First, I know you've been trying for a while but remove all the current constraints (painful I know but). Do this for clarity as ....
The view should be the size of the scene, it looks like you want the scrollview to be the full screen so that too needs to be the size of the scene.
e.g. if you are designing at 6Plus by default the scene size is 414x736 so the view and the scrollview it contains should also be 414x736.
Only the content view needs to be the size of the real content you wish to show. Let's say for arguments sake that the content is 414x1000.
Now the constraints for the scrollview are simple. It needs zero spacing to all it's edges.
You can add the content view to the scrollview in a couple of ways. The way I try to do this varies from project to project and depends mostly on how complex the scene is. If it's a really busy scene I keep the content view outside of the scrollview in interface builder so that I can work on it easily and visualize the whole of the view. Then I add the content view to the scrollview in code.
If its a simpler view You can add it inside the scrollview in interface builder. Ultimately whichever way you do it, you can lose visibility of the content view in interface builder because the contentview is larger than the scrollview and the content gets obscured. So play about and find a good way for you.
Define the content view and all it's subviews. The content view needs to be taller than the scrollview otherwise it wont scroll. All of the content view's subviews need to have defined heights from top to bottom and widths from left to right. In your case the scrollview is scrolling vertically not horizontally so all the widths need to add up to the width of the scroll view BUT the heights need to add up to the full height of the content view.
Note: if you do this proportially your life will be easier later. If you do all this with fixed heights the storyboard will break on different device sizes.
Now the "tricky bit" and it's a bit counter intuitive. You need to pin the content view to the scrollview, remember the height of the content view is taller than the scrollview. In all other circumstances in Interface Builder pinning a view to a superview (0 padding) will adjust the height (or width) accordingly. For the relationship between a scrollview and it's content view this doesn't happen.
First pin the contentview
Notice the -400? Remember the content view is taller than the scrollview and we will change this immediately.
Select the bottom constraint (-400) that we have just created:
Select the drop down arrow next to the constant value:
Select Standard Value and type in 0 for the constant.
You should now have a storyboard with no broken constraints and if you build and run you should get a scrollview as desired.
Your bottomspace to superview on your content view is set to -74.0, I don't know if there is a reason you had to do that, but try setting it to -8.0. I think your scroll view is scrolling up to the 0.0 mark automatically

UIScrollView Causing "Misplaced Views" AutoLayout issues

I'm running into a strange AutoLayout related issue when I use a UIScrollView (the issue does not occur without it).
I have a UIScrollView that is constrained to the boundaries of a UIView (contained within a UIViewController), and within that, I am attempting to place a UILabel and UITextField side by side. I have constrained the UILabel to the left and upper boundaries, with it's width and height constrained (see screenshot below):
Right next to this UILabel is a UITextField, which is constrained to the left, top, and right, as well as having the height constrained. However, this results in a "Misplaced Views" warning, that states "Expected width = 163, Actual width = 413", shown in the screenshot below:
When I choose to "Reset to Suggested Constraints", the "Misplaced Views" issue disappears, but in it's place I am left with a width constraint of 413 points, which is something I'm hoping to avoid, as I would not like this UIViewController to be horizontally scrollable on smaller devices.
A scroll view has a size (the size it takes up on the screen) and a content size (the size of the entire scrollable area). In Auto Layout, the content size is automatically computed from the constraints of the items in the scroll view. This is a problem, because you are trying to make the scroll view have the same width as your screen, and then have the items constrained to that. When you do that, Auto Layout insists that you give your text field an explicit width so that it can calculate the width of your scrollable area.
To do what you want, do the following:
Add a "content view" to your scroll view. This view will be the only top level item in your scroll view. It will hold all of your content as subviews of it. Drag out a UIView and add it to your scroll view. Constrain its top, leading, bottom, and trailing edges to the scroll view. Constrain its width to the width of the scroll view. Give it a height constraint and set it however big you want your content area to be.
Add all of your labels and textfields to this content view. Now you can constrain them centered in your content view or constrained to the edges, and it will work as you want.

Dynamically set UIView size depending on height of grouped table view

Setup: I have a UIView with a scroll view nested within it. Within the scroll view I have a label, uiimage, and a tableview (grouped). The label, uiimage, and tableveiw are populated by a webservice. The last section in the grouped table view contains text that will never be the same and could be as long as 5 characters to 250+. Also, this view is pushed from a basic tableview (so it has a navigation bar. If that matters at all).
Expected: The uiview should extend in height depending on the height tableview extends to. Then I will be able to set the scrollview to accommodate the height I need to be able to scroll.
Problem: I'm not quite sure how to approach the issue. I really only know how to change the height to fixed values, which will not work properly in almost any scenario.
Am I using UIScrollView incorrectly? Do I need to resize the UIView at all?
You don't have to modify your UIView frame size, which has to be the size of your screen. The UIScrollView frame size must also be the same, it represents the part of its view actually displayed.
What must change is the UIScrollView contentSize, which defines height and width for data inside it ;)
You can calculate it using each inside element's height and by adding the correct margin.
Thus, you could have a UIScrollView content size of 320 * 600, which will let you automatically scroll down.
In fact, you have to display your content independently of the final frame size. If you have a content of 500*500, just display it inside your UIScrollView. Then tell it the size of it's content, and it will automatically set scrolling possibilities if needed.
Turns out I had to create a UIView programmatically and set it as the header of the UITableView. It works perfectly now. :)

Why can't I tap input elements after I resize a scroll view?

I have a sample project that uses the metrics from notifications for resizing the keyboard when a text field is focused.
http://www.smallsharptools.com/downloads/ObjC/KeyboardSize.zip
The series of text fields are all wrapped inside of a UIScrollView and when the keyboard is shown a notification is sent with the height value. I use that to decrease the height of the UIScrollView so that all of content can scroll inside without being covered by the keyboard.
But I find that when I do this the other text fields sometimes cannot be tapped. They seem to be covered with a layer that I cannot see.
What can I do to ensure that the input elements in the UIScrollView remain accessible when the height is changed?
FYI: You can see in the sample project there is a blue marker on top and another red one at the bottom. The view controller which handles the resizing is CMScrollingViewController which is inherited into KeyboardSizeViewController so that this behavior can be used by multiple view controllers.
I am hoping that this problem can be fixed so this simple code can be reused.
I figured out my problem. I was setting the view which goes inside scroll view to flex the height and width using the autoresizing mask. Once I commented out that line of code this problem went away. It seems it was resizing the view but I could still see the contents of the view but it was outside the bounds of the view so it could not respond to taps.
//self.subView.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);