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.
Related
I've had several attempts to try and convert my iPad app to make it universal.
I'm only supporting landscape on iPhone / iPad.
My existing iPad setup uses a storyboard without autolayout, which works fine.
My app had lots of images and about 10 screen each with a minimum of 6 views on each, however some have 20 or 30.
I decided a couple of weeks ago that it would a far greater nightmare with all the images, so I've created paint code classes for all my images.
When I first turned on sizing classes / autolayout, Xcode asked if it should enable suggested layouts, this seemed to make sense. However it's made a real mess of the any / any layout.
Without adjusting the sizing classes setting any / any, I tried to install constraints for differing sizing classes. I want to make views bigger to fill the space, so I installed constraints with equal width (with aspect ratio) to subview with a multiplier so I would get proportional sized views. However this means I have about three sets of constraints per view. Which is a nightmare on my simple screen.
I then thought it might be better in my case to leave my iPad storyboard and have an iPhone storyboard. But my iPhone 6+ layout won't look very good. Turning on sizing classes made little sense with multiple storyboards.
I'm now thinking I could click the sizing class to regular / regular and compact / compact and have different views for each?
However any / any, which I can't get any sort of layout to look good, will still need views?
I'm also wondering if should let Xcode setup autolayout when I first enable it? As I say any / any looks bad.
I was thinking I could just plop my views in a vague position with any / any, apply suggested constraints, then click / flip to compact / compact and regular / regular and move things around.
I guess I'd also need to do that for compact / regular for 6+ too.
I'm just not sure what steps to take, I can't even think of workable plan b.
I've watched a million videos and feel I understand but I can't put it into practice.
HELP
My Suggest steps would be:
When we use autolayout and size classes, We always take start from wAny hAny
Take your simple Screen First Let say your login screen on ipad LandScape without autolayout will look like this:
Now you enable autolayout and size classes. Change Scene size to inferred (600, 600).
Now your view look terrible:
First Adjust it by just moving the views to center and correct places like this.
Now we are all set for applying autolayout constraints.
First give constraints to parentview(grey view). Unless parent view has correct constraints, childs view cannot be given correct constraints. So always make sure parent view have correct constraints.
Now we select the grey view and apply constriants like this:
Center vertically and horizontally in container.
Add width and Height Constraints. You got options. Give fixed width and height and modify it for different classes. like this:
Or you can add proportional constraints for width or height.(Better)
Now start with childs. Give them leading, trailing, top and height.
Height of label is 50 for wR hAny and 40 for wR hCompact
Final Results:
IPAD LANDSCAPE:
IPHONE LANDSCAPE:
Autolayout and size class are great and easy when someone get used to it.
HOPE IT HELP.
You have 2 options
1) Create separate layout for iPhone and iPad. In this options you might have to compromise targeted customization for iPhone6+. This option will consume less time, and if you have a time constraint or you think that you are not convenient working with autolayouts then go with this option.
2) Using any/any size class and add constraints to make you interface alright for iPad. After that only modify/add those constraints for iPhone specific size classes which needs to be adjusted. Once you have layout set with any/any for one of the device either iPhone or iPad, you will be surprised to know how much less constraints you will have to modify for specific size classes. This option requires good understanding of autolayouts or even if you are not convenient working with autolayout but willing to try and have no problem with time constraint then you should definitely go with this option.
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.
Im starting to experiment with storyboard. As you can see I have chosen the storyboard size to be height=regular and width=compact, which says “For all iPhones in portrait”.
The simulator I am using is iPhone6 however when I run everything is slightly off to the right.
Can someone explain what is happening or what I am missing?
The problem is that (as described in the comments) you are positioning the views without AutoLayout. When you just drag and drop the views, it's actually setting the frame's positions and sizes. The main problem with this approach is that it doesn't set the position and size in a proportional and related manner, taking in consideration the container. This is why you're getting the view at the current position. If you run in another simulator, maybe you can get the correct position, or maybe not. What you can do to change this is apply auto layout constraints to those views. There's a special constraint to center views horizontally. With autoLayout you can go further, specifying relation between one or more views, and those views not necessarily need have the same container view.
One quick example:
Notes:
I'm using universal storyboard to take those screenshots. It's more flexible and with AL you don't necessarily have to concern yourself with the size, as views adjust themselves depending on the constraints applied to.
EDIT:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Introduction/Introduction.html
This is a link to auto layout guide provided by apple, a great tutorial on how to get your hands dirty in this little world.
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
I am working on an iOS application and it will be compatible for all devices iPhone 3.5, 4, 4.7, 5.5 inches and iPad also.
I am designing a screen it has 5 subviews, as i view this screen in different screen it does not resize properly.
I am using Auto-layout to manage that screen and I have set the every possible constraint to manage this screen.I have to manage the Subviews height and width as the devices changes.
Following are the steps taken care by me
1)Set the Equal Height Constraint for all subviews
2)Equal Width Constraint for TopView1 and TopView2 set the High priority and set the proper Horizontal spacing, Leading, trailing edges for these two top spaces accordingly.
3)Equal Width Constraint for MiddleView1 , MiddleView2 and MiddleView3 and set the High priority and set the proper Horizontal spacing for these two and vertical spaces from TOpViews accordingly.
4)Set the Width Constraint for bottomView and set the High priority and set the proper Horizontal spacing for these two and vertical spaces from MiddleViews and bottom spaces accordingly.
Prior to this i have not used auto-layout in such complicated way.
Following are the screen shotes depict my problem.
EDIT:
#Ash Furrow please see attached a screen shotes with constraints.
I am laying out the base screen on Any Width Any Height
Please anybody suggest me how should i manage this view
Hmm. Looking at what you've done and the feedback to your question, everything seems correct.
I think I see the problem. The issue doesn't appear to be with your storyboard (here in case anyone is interested), but rather the use of Xcode. Instead of changing the view controller's simulated "Size" metric, use the Assistant Editor to view a preview of whatever device you want. I've tried that, and ran the code, and in both cases they appear to work.
So to recap, use the Preview in the Assistant Editor instead of changing the view controller's properties to resize a view hierarchy.