Autolayout is sizing objects in a UIScrollView incorrectly - ios

I'm trying to create a layout using Interface Builder, size classes and a UIScrollView.
The UIScrollView is meant to be full screen, 0,0,0,0 left, top, right, bottom.
However when I set the constraints of my objects, (labels, textfields, etc) to be 20 away from the right size, it doesn't appear correctly in either Interface Builder or the simulator.
I've tried several things to fix this, putting the objects in a view container, making a new storyboard file etc and nothing has worked.
Hopefully someone can figure out what is going on, I don't want to resort to springs and struts.

Related

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.

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

UIScrollView zoom with Autolayout

I know there are a couple of questions around but I could not figure out how to do this (none of the answers there helped me), so here is my version of the question.
I have an UICollectionView which is set to scroll horizontally. Each cell has an UIScrollView inside and inside the UIScrollView I have an UIImageView.
Now, the images displayed by the UIImageView are loaded from the internet and I can't figure out a way to make the zooming work correctly using storyboards and autolayout.
If I set constraints that tie my UIScrollView to it's container everything is ok. The moment I tie the UIImageView to the UIScrollView XCode starts to complain that the UIScrollView's size is ambiguous.
If I don't make any constraints in InterfaceBuilder the images are not the displayed in the correct size (doh!).
So, I'm stuck. I don't know what kind of constraints to make and which view needs to be tied to what. I know that my perfect world result is a view controller that behaves like the native iOS Photos app. That is, the image is displayed as large as the screen (with a black band at top and bottom or left & right depending on image's orientation) and that you can zoom it in and pan it around.
Help please!
Note
I did read these posts before posting my own question
UIScrollView zooming with Auto Layout
UIScrollView Zoom Does Not Work With Autolayout
“Pinch to Zoom” using AutoLayout
I don't know if it'll help you with your zooming problem but Apple provided a technical note about using scroll views with auto layout: Technical Note TN2154, UIScrollView And Autolayout
The important part with scroll views is, that the constraints of the subviews inside the scroll view are not bound to the scroll view itself, but to the scroll view's parent (in your case the collection view cell)
It works
You can easily do it. Well not really easily, i have been struggling for quite a while!
I managed to implement auto layout within the scrollable area. Just it is vertical only
Set intrinsic size to a "placeholder" (to scrollable view)
Don't set contentSize at all
Attach right constraints to the wrapper (so it will be relative to the parent view)
self.view.addConstraint(NSLayoutConstraint(
item:self.view, attribute:.Trailing,
relatedBy:.Equal, toItem:contentView,
attribute:.Trailing, multiplier:1, constant:0))
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
So, in your case, your contentView right side should be attached the right side of the image
Try it out, certainly you will have your zooming to work
Here is an example, it may help you
https://github.com/nchanged/swift-content-manager/tree/master

Xcode IB Storyboards orientation and container views

In an IOS 6 iPad app, I have a container view controller with multiple container views. Currently I have locked my app to landscape and works fine but I'd like to support portrait as well. Everything is set up using auto layout and constraints via Interface builder. If possible I'd like to keep one storyboard for consistency, maintainability etc.
The layout is this: Header, Left-side menu, two content panes (side by side in landscape) and a foot pane, I have all panes resizing except the content. When rotating from landscape to portrait I'd like one content pane to slide below the other (currently it blows off the screen), and both to stick to the edges of the container view.
In HTML5/CSS3 this would be easy to do but I'm stuck in IB, any help/ideas would be great!
Thanks!
EDIT:
Solution -
Following #Charles A.'s suggestion, I linked the NSLayoutConstraints to IBOutlets and manipulated spacing/priority in code. Where I really struggled was using Height and Width constraints. If you moved anything, Interface Builder would delete or override these with Leading/trailing & Top/Bottom constraints. I finally gave in and got rid off all height & width constraints, and used only leading/trailing/top/bottom.
2 things I figured out: Constraints have milestones(one at priority #750 for instance) so if you pragmatically change priority from 749 to 750, you will get:
Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported.
But if you changed from 750 to 800 you are fine.
Also, after manipulating constraints, I needed to call:
[self updateViewConstraints]
I had found a post that suggested [parent updateViewConstraints], which didn't work, the one above did!
Anyway, I hope this helps others in this spot since there's not much out there.
It's hard to answer the question specifically without knowing how your layout constraints are setup to handle your two content views. Having said that, I would probably go about this UI by having my layout constrained similar to this (I'll use the visual format to describe, I'm assuming that the superview is the parent of the two content views in this case):
|-[contentViewOne]-0-[contentViewTwo(==contentViewOne)]-|
If the constraints are setup as above in the storyboard, you could create an IBOutlet of type NSLayoutConstraint* and connect it to the horizontal space constraint between the two content views (the one that specifies a constant value of 0, in my case above). When you animate from landscape to portrait, just set it's constant value to the negative width of contentViewOne. This should have the desired affect. You'll obviously also have to set it back to 0 when rotating from portrait to landscape.
It's worth noting that I assume your content views are equal width. If they're not you would potentially also need to make an outlet for a width constraint on the one sliding under in order to temporarily set it to the same width as the one covering it.
There are many potential ways to address this layout using autolayout. What I've described above is just one such way. It comes down to what makes sense given the layout you already have.

Resources