Why isn't this UIScrollView autolayout working? - ios

I have a simple program with a UIScrollView, and one UITextField inside it. I constrain the UIScrollView to have 0 space on all it's four sides, which I thought would make it fill the screen. And I constrain the text field to be the standard space from the edges:
But when it runs, it does this:
I see the technical note, but I don't understand it yet.
The field will fill the screen if I give a width=280 constraint, but that goes against the spirit of autolayout. I want it to adapt to the width of the screen, not be hard coded to the 280pt width in the storyboard. How to do that?
Here are the layout errors:

I found an answer to my own question.
The answer is contained in the tech note, but in my opinion not explained in enough detail. This blog post helped me: http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
Summary: put a width constraint on the text field to shut up the IB errors, but then check the "Placeholder, remove at build time" checkbox for the constraint (in the attribute inspector in IB). Then you can add better constraints programmatically, in the view controller's viewDidLoad method. In this case I want constraints that connect the text field's left and right edges to the scroll view's superview edges (and thus the screen edges). You apparently can't make constraints like this in IB. With those two constraints, it all works correctly, even as the screen is rotated.

Related

UISTackview constraint error in a UIScrollview in viewcontroller

I was trying to add a UISTackview in a scrollview. I believe the UIScrollview setup is right as the following screen has scrolled. Please note that it does not have any stackview, I have added a button with big top constraint so that I can see whether the scrollview works or not.
Next, I added the stackview and just added the top, left, right constraint but not bottom constraint like the following image. However, since there is no bottom constraint, the scrollview does not work.
When I added the bottom constraint, it shows the error like the following image because none of the textfields has height constraints.
If I change the distribution to "Fill Equally". The textfields are taking too much blank spaces depending on the screen size.
How can I use the stackview inside the scrollview. I want to use it as I want some of the views hidden based on conditions and claim the space. Any suggestion would be helpful. Thanks
Your second image is correct - but you need one more constraint.
Add a constraint from the Bottom of the Stack View to the Bottom of View (its superview), but set it to >= 0
A couple of tips...
rename your UI elements... it gets very confusing to refer to elements by default generic names (you have more than one View, for example).
give your objects contrasting background colors during development... makes it much, much easier to see the frames.

ios - UIScrollview w/ autolayout on Xcode 6

I have been struggling for days with this implementation, and even though I have tried to do every tutorial I found on the web, I still cannot make things work the way I want.
Basically, I am trying to put my login form in a scrollview, so that it takes the whole screen at first (and on all iPhones / iPads), and if the keyboard appears everything should move. The problem IS, my view doesn't take the whole screen... Either it is too large, or too high, even though in Interface Builder everything seams correct (from layout to constraints). Below and image of the layout I want to achieve (I am using an universal storyboard, with Size Classes and Autolayout enabled):
http://img4.hostingpics.net/pics/829115app.png
Can someone point me out on achieving this layout ?
Thanks in advance.
I would suggest pinning top, leading and trailing spaces of your scroll view to its superview. And set a bottom space constraint less or equal to the keyboard's height if you set it to 0, the scroll view won't be able to resize.
With your form layout set vertical center constraints and top space to superview constraints for your top label being more or equal than the distance you set in the IB, and then you can set relative space constraints between each of the components.
Hope I answered your question.
Edit: Just the provided project and got it working. I think the problem is caused by it being a containerView inside a scrollView. And both the container and the scrollViews content view adapt to the size of its subviews. Because of that, setting relative constraints won't help.
What I did was to set an explicit size (screen's size) to the containerView and setting setTranslatesAutoresizingMaskIntoConstraints(true) to it.
I modified your project and uploaded it here

Adding/removing views dynamically with autolayout

I have a pretty complex view and am trying to update it to work with autolayout (while I learn autolayout at the same time). Here is a screenshot of my view:
The only thing that you can't see is that all of these views are wrapped in a containerView and that container is sitting in a vertical scrolling UIScrollView.So if there was a really long description or something you would be able to scroll vertically.
My first problem is that I can't figure out how to get the descriptionView (red background) to adjust it's height dynamically (I have scrolling disabled in IB and again in code). I think it might be related to the bottom constraint to the imageScrollView.
The second problem is that the imageScrollView needs to be removed half the time. It holds multiple pictures of an item. But sometimes the item doesn't have pictures so I just want to remove the scrollView in that instance. I call removeSubview in code and want things to just readjust without having to set up a bunch of new constraints. So I added a top space constraint from the Question/Comments label to the bottom of the description and changed its priority to 900 instead of 1000. This seemed to solve my first problem and when I remove the imageScrollView the description view resized to the size of the content. However my scrollView that holds all of the content didn't scroll anymore, I am assuming that the containerView's height got screwed up or something.
Edit: the more I think about this the more I think that figuring out how to add a contraint for the size the descriptionView's height to match the content will solve the other problem as well. Here is another screenshot with the current constraints.
SOLUTION
I don't feel it is fair to post my own solution as the accepted answer. So I am posting my solution within the question, and giving the accepted answer to Nikita for trolling all the questions related to textViews being sized to their content.
My first problem is solved by using this: Github - Resizable Text View
The second issue was just a matter of setting up the constraints correctly. The red textView had a constraint to the bottom of the superview(contentContainer) (the superview which sets the height of the the main scrollView.) So when I removed textView then the contentContainer view didn't have a height constraint. So I ended up removing the constraint from the textView to the superview (which is the contentContainer) and made a constraint from the bottom of the commentTextView to the contentContainer. This solved the problem. Whenever I remove the red textView everything shrinks up the way I desire.
I'm not sure, that my solution is the best one, but I've done it in the following manner (I think that will help you with red text view): How do I size a UITextView to its content?
Unfortunately, I didn't understand you about second problem. Please, provide more details. Thanks!
Don't remove the image view. Just give it a zero-height constraint. That way you don't have to mess with any of your other constraints.

AutoLayout - how to bind two view and change size accordingly

i want something who seems simple at first glance, but i can't figure out how to make it nicely from IB.
I want something simple, let's say i have two view into one parent (a view container that hold the two children). What i want is that they are each connected to vertical space at 0 px (one to his top the other to the bottom of the other). So that when one of them change his size the other occupy the remainder size, and so there're will still be connected at 0 pixel each other.
I've put two screenshoots of what i want.
I've tried lot and lot, and nothing is working like i'm expecting.
What is strange that even if i put the priority at the vertical space, the other constraints take priority, and i just get a warning from XCode that my verticalSpace constraint is wrong.
Could someone help me ? I didn't find a specific tutorial on this kind of view managements.
Thanks
* EDIT *
Ok i figured out:
I finally read the entire tutorial of Ray as suggested, and it helped me a lot (to my defense, i have read before the IOS official documentation about constraints, and it has confuse me more than helped me). To me, what was hard to understand is that now you can't change UIView by frame but now by constraint. When I understood this, it was really easy to make the changes.
By the way i tried the #Handsomeguy's response, and it worked like a charm.
I think you'll need at least one height constraint (with IBOutlet to your view controller) on one of your views... when you change its constant value, the other view should automatically change. You can try on storyboard first, and then write down the logic. But without an height constraint on one of them I don't think it will ever work.
I was able to do it by setting constraints in interface builder:
vertical spacing: top layout guide -> yellow
vertical spacing: yellow -> red
vertical spacing: red -> bottom layout guide
height: yellow
Set an outlet to the height constraint, then to change the height of the yellow view just use _height.constant = NEW_HEIGHT
You can probably omit the height constraint if the top view reports it's intrinsic content height appropriately.
Use autolayout. You need the following constraints:
both views pinned to left and right edge of containerView
redView top pinned to containerView top
yellowView top pinned to redView bottom
yellowView bottom pinned to containerView bottom
height constraint on **either* redView **or** yellowView!
This is very easy using this category:
https://github.com/jrturton/UIView-Autolayout
UPDATE
I just noticed you said you wanted to do it in IB. You can use the same principle here, but I find it is much more convenient (and also easier to read later) if you use the category mentioned. There will be very few lines of code, and the code will clearly show the intent.
** UPDATE 2**
An explicit height constraint may not be necessary if the intrinsic size on one view is changed. This depends on what kind of views the yellow and green views are.
Without auto layout it would be as easy as putting an anchor-bottom on the yellow view, and putting an anchor-top on the red one. Now, when you change the parent view, the views would resize 50/50.

Resizing a UITextView in UIScrollView using Auto Layout issue

I really hate to ask here because I usually try to figure things out on my own. But on this one I've stuck for days and can't find a solution anywhere online.
I have a ScrollView containing multiple subviews. I've got an image view and two labels at the top with fixed heights. Then there is a UITextView and another ImageView (see pictures).
I add the text to the text view programmatically so it should have a dynamic height and the ImageView should move to the bottom so you can scroll. I don't want the TextView to be scrollable in itself but I want all the subviews to move as well.
I know I should be able to solve this issue using constraints. But I feel like I've tried everything and nothing worked yet. It worked when I disabled auto layout and moved the views manually. I'm wondering if there is a better way though.
As you can see I pinned the TextView to the ImageView above with a 1,000 priority and to the ImageView below with a 1,000 priority. The height constraint can not be deleted so I set it to the lowest possible priority. The ImageView on the bottom is pinned to the bottom of the superview with an absolute height. Its height constraint also has low priority. (I can post an image of the ImageView's constraints, if it helps)
I also tried adapting the frame programmatically but this is not working well in combination with auto layout. (If it helps I can of course post the code)
What am I doing wrong? Shall I just disable auto layout and do it manually? This seems unclean to me. Is it even possible to do?
I really appreciate your help :)
Greets,
Jan
Make sure the Scrolling Enabled attribute on the UITextView is unchecked in Interface Builder. I believe that the Auto Layout system takes that into account when it calculates the intrinsic content size.
If somebody is struggling with a similar problem: This is what I ended up doing:
Remove all subviews from the ScrollView in IB
Programmatically add a single UIView to the ScrollView.
Add all the views to the UIView as subviews (move them using setFrame)
Set the Frame of the UIView appropriately to the subviews
Set the ScrollView's contentSize to the size of the UIView.
A little more work but it finally works. This follows Apple's mixed approach guidelines that can be seen here (look for UIScrollView): http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/index.html
The problem is the height setting. You somehow have to try to delete it. If you have added other constraints that are "sufficient", it should become deletable.
At the moment you have one user constraint for the height that is "Greater or equal" and an "Equals" constraint as well. Clearly, those are not working well together.
Maybe there is a conceptual error as well. The lower image view should not be fixed in position, so the distance to the lower image view will not be a "sufficient" constraint to let you delete the fixed height.
I think it should work if
the lower image view has a fixed height and
a fixed distance to the text view above, and
the text view has a minimum height as well as
a fixed distance to the image view above
(which should be fixed in relation to the superview).

Resources