autolayout view resizes upon interaction - ios

Within a container view, I have a subview constrained to 8 pixels from the top/bottom/left/right of viewController's view. There is a button that adds an (non-autolayout) view inside of it, and another button that causes an (autolayout) view to expand below it. When the view loads, everything is as it should be, but as soon as either of the two buttons are pressed, the view in question shrinks another 8 pixels or so in width.
I've tried calling layoutIfNeeded() at a couple points in the script, but that hasn't worked. Does anybody know what might be going on here? Is there some conflict because I'm mixing autolayout with non-constrained views?

After messing around with it for a couple of hours, I found that changing the way the view was constrained in IB fixed the problem.
I don't understand why this worked, but incase anybody else ever runs into a similar problem, instead of constraining the left/right to container view, try constraining the width of the view to be equal to the container view (minus something if you want) and add a center in container constraint.

Related

How do I prepare a UIViewController's view for being added to a UIStackView?

This is what I'm trying to do...
I have one view controller that needs to dynamically display different subviews based on the presence of some data.
Here is a simple mockup. Each colored block represents a unique subview.
Sometimes the green block needs to be at the top, sometimes the green block won't display at all, sometimes the light blue block will be something different, etc.
Each subview has interactive elements, so I've been creating and adding them like so:
Defining a new view controller
Defining its view
Calling addChildViewController and didMoveToParentViewController
Calling addSubview on myNewViewController.view
Using SnapKit to make auto layout constraints to position the view
I want to transition to UIStackView because it seems a good support system for this view because all I need to do is stack its subviews. I'm seeing many conflicting constraint errors and unexpected view frames when trying to add subviews with their own inner auto layout constraints.
Question
Am I setting myself up for failure here by embedding the views of 4-6 view controllers in the view of one view controller?
Also, how do I give the added views properties like minimum heights or content sizes without seeing many breaking constraints with UIStackView? (So they can stack, but one of them is say, 400 tall, and the other is 200 tall)
Answer
You can absolutely do this using UIContainerViews combined with UIStackViews and UIScrollViews, it's a complicated setup so here's a starter project to get you started:
https://github.com/Rnorback/ScrollingStackView
Here's what that project looks like:
You want the containers to have different sizes. In order to do that, simply add height constraints to the containers with Autolayout. If you want to change the height of the scrolling. Then you'll need to change the height constraint of the UIStackView.
Brief Explanation
When creating this setup, you have to make sure the UIStackView distribution setting stays in fill. That way you can set height constraints on UIContainerViews.
When setting up anything in a UIScrollView you have to make sure that the object is pinned to the edges of the scroll view and has a defined width and height, otherwise the scrollview will throw a constriant error. I think of it like the scrollview tries to press in on all sides of your content view and if any side gives, the scrollview won't be able to present it properly.
Hope this helps.

Why do autolayout constraints in Xcode cause my subview to disappear off screen?

I'm trying to figure out how to use autolayout, and there seems to be a lack of info about it on the internet. I placed a view within my view controller with three buttons inside it. Before I place any constraints, the buttons show up on the preview. However, as soon as I make ANY constraints, the whole sub view completely stops showing up in the preview. I made a constraint to center vertically, and then one to place it 25 pixels from the left edge. It should know exactly where to place it, but still nothing shows up.
Any ideas on why constraints cause my buttons to not show up?
With Autolayouts the constraints should be as clear as possible. You can try by adding size constraints as well as fix(right, top or bottom) constraints if necessary.
When you don't use auto-layout it positions everything manually. When you enable auto-layout it switches this behaviour off so you have an unconstrained object, which is why it dissappeared.
Turns out I didn't have constraints on the size of the sub view, so it didn't know how to center it. I didn't think I needed that because I thought it would default to what it's already at.

Constraints in ios

I am learning constraints and spent whole day applying them to the following screen.It is not getting displayed properly in landscape mode.Basically i am not getting how to fix vertical space between ,say, label-Welcome to BBBB and textfield-username so that textfield always appears below the label yet the spacing between them is adjusted according to the screens of different size. If i go for Pin\Vertical space, it automatically fixes the constant value.
Remove the label (or just move it out of the way).
Fill the space that you want to resize with a view.
Constrain this view to the objects above and below and to the sides of the parent view.
Put your label into this view and constrain it to the top of this view and centred to it.
You may need to change the constraints on the objects above and below it to stop them from changing height in an unwanted manner.
This new view should now resize as the device changes orientation but the label should remain at the top of it.
Repeat on other areas of your layout (i.e put things that are not moving around as you want them into sub views and constrain these views to resize accordingly). Experiment with using variable heights, fixed heigh constraints and 'equal heights with' constraints on the views that you add to get them to resize as you need.
Edit: but you have a lot of vertically stacked items in that view - you may never get them all to fit into a horizontal orientation. You may need to remove a few, or add a scroll view or force that view only to layout in portrait mode or... Don't forget to check that it works on all devices you are targeting.
#Ali Beadle was right. Since i had a lot of vertically stacked items, lining them up in landscape mode was not possible. So, i went for scrollview.
I have taken a ScrollView first and then a UIView named ContentView on that ScrollView. I have made the width of ContentView equal to the width of parent UIView and kept its height fixed to 568. In my code i set
_contentViewHeight.constant = self.view.frame.size.height;
Now it scrolls in landscape mode while in potrait mode, it does'nt scroll.
I run into Autolayout problems all the time. But I finally figured out a way to overcome a lot of issues that arise from it.
I simply will use a container-View like ScrollView or even a plain old UIView, place all my controls in it. thats it. this makes things a lot easier for autolayout to figure out the constraints. in your case you could just use a UIView.
-start off by removing all the constraints you have I would start by selecting each control in the XIB and see if it has width/height constraint, select it then press the delete key then at the bottom of the project explorer you'll see all the constraints that auto layout has select each one then delete. that should get rid of any complaints that auto-layout might have.
-Place a UIView object inside your main View then
-move all the controls inside it. Then
-add the necessary constraints for the container view so it'll resize in different orientations and don't worry about any constraints inside the container view (auto layout will figure them out automatically).
that does the trick for me usually.

navigation bar possibly causing UIView offset

I have a view controller that consists of two UIViews. One view is the super view and the other is a subview. Both views are the same size 320X568 and have the same origin (0,0). I added constraints to the subview by first setting an aspect ratio to itself, then an equal width ratio to the superview with a multiplier of 1. I then centered the subview horizontally and vertically in the container. When an up drag gesture is recognized, the subview is suppose to move up a certain amount using CGRectOffset. I noticed that the view wasn't ending in the right position, so I removed all the offset code to see what was going on. In viewDidLoad I check the origin.y of both the super view and subview and its 0 - which is correct. However, once the up drag gesture is recognized, I do another NSLog for the y origins and the subview prints -31.5 and the superview prints 64. Not sure how this is happening with all the CGRectOffset commented out. I'm thinking this might have to do with the navigation bar but I'm not sure.
I don't know what the deal is with the CGRectOffset, but I do know what the "problem" is without it. There's no problem! The only thing here is that you are checking the origin.y of the views too soon, namely in viewDidLoad.
Remember, in viewDidLoad nothing has actually happened yet. The view controller has a view but that's all. In particular, the view is not yet in the interface and has not been given its layout yet.
So it's really just a matter of knowing what the events mean. You're assuming that viewDidLoad means the view is in the interface and has its position and size. It doesn't mean anything like that. If you want to know what the view's position is after layout, you need to wait until after layout. Like, viewDidLayoutSubviews is a good place. It means that layout has just occurred!
As for the 64 value, it's just what you would expect. You have pinned your view's top to the top layout guide - which means the bottom of the navigation bar, exactly as you have suggested.

UIScrollView offsetting content in contentView

I am having a very frustrating issue. I know there are all kinds of issues with UIScrollView in iOS7 and XCode 5. I need to implement a scrollview and there are all kinds of tutorials showing you how to do it by switching off auto layout but that then messes with the rest of the views in my app.
I tried the fix of putting my subviews into a container UIView and placing that in the UIScrollView and setting the scrollview's content size to the size of the contained UIVIew. That didn't work. Now I am working with placing everything in the scrollview and it all works with one exception. When I load the view on the simulator or a device the content view is moved down but somewhere around 60 points or so. See image below.
That white space below the title bar on the right is still the scroll view as I can press and drag within it. Adjusting the contentOffset doesn't do any good as that just scrolls the view down slightly. I have no idea what to do here.
Just a little more info: I setup the scrollview and all the subviews in storyboard and the connected them up. Not sure if that has any bearing on it.
Thanks in advance for any help you can provide.
I think your Scrollview top space constraint have 64 pixels. That's a problem. So, set your top space constraint value to 0.
You need to add the constraints before view displayed then contentsize will be set automatically.
Check UIScrollView's autoresizing mask. It has to be set like this.

Resources