I am working on an iPad app and want to support both portait and landscape orientation.
Currently, I am seeing three ways to handle orientation:
1) Apple recommends using two view controllers (http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrientationChanges.html)
2) The Beginning iPhone Dev book I have uses a single xib file with multiple UIView (one for portrait, one for landscape), swapping the view in the willAnimateRotationToInterfaceOrientation() method.
3) Others have said the "proper" way to do it was using layoutSubviews and autosizing mask.
Before, when I build an app, I would write my entire app purely in code, including interface setup and layout. The result was I ended up with a massive and very painful to tweak interface code.
Now after writing a number of apps in purely code, I kind of appreciate why there is Interface Builder - to help manage the interface and more so, a view controller should ideally only be for managing data and sending it to the views, not managing how the views should look.
Using Interface Builder, it makes sense to have two separate custom UIViews, one for portrait and one for landscape but I've been told otherwise that layoutSubview is the better option.
But if I were to use layoutSubview, that would mean I have to go back to writing and managing my interface using code, which doesn't seem right to me.
Is using layoutSubviews() really the way to go ?
I really don't see any benefit it has over other method. Some say layoutSubviews allow you to animate the transition to the other orientation.
My two interface isn't a simple resize button or text width when the device rotates. I have adjacent sliders next to text fields that should be stacked vertically when rotating to landscape and other sliders that needs to be moved to the other side of the screen etc.
edit
might be a duplicate questions of:
Handle iPhone orientation Landscape/Portrait
iPad/iPhone multiple orientations best practice?
Moderators can close if need to.
Related
I am trying to layout user interfaces differently for Portrait & Landscape orientations. The difference comes in the following ways:
I have few UIStackViews. Some of their axis becomes horizontal in landscape but vertical in portrait mode,
The order of buttons in UIStackView may be different in both the modes,
A button which is added to subview1 in landscape needs to be removed & added to subview2 in landscape. subview1 may not be present at all in portrait mode,
Autolayout constraints are different in both the modes.
I started with vary for traits in XCode but it seems to have limitations. I am manually switching constraints in the code on observing trait collection changes (viewWillTransition:...) but it seems clumsy. Is there a better way or the best way would be to have duplicate sets of controls for both the modes and hide the ones not needed in landscape/portrait modes?
The interface builder is really powerful if you use it right, I'm not completely sure what you're trying to do, it'd be useful if you share some screenshots at least. I'm assuming that you're every subview of the UIStackView is a button, or it contains a button, in that case what I'd do is:
Having 2 different UIStackView, one for landscape and the other for portrait.
Add variants to the installed interface builder property for traits. So only one of the two UIStackView will be installed at a time.
For every UIButton add the event, connect it to the respective IBAction or selector. This will work even if there're 2 buttons that do the same.
So regarding your issues:
The axis itself wont change, but this will work because there're 2 version of the UIStackView.
You can choose to arrange the button on each UIStackView.
Just add the buttons wherever you want on each UIStackView.
Set the constraints as you want depending on which UIStackView you're working on.
An I missing something? please update your question with more information so people can help you in a better way.
What I have done is to observe the UIDevice.orientationDidChangeNotification and update the necessarily constraints to achieve different layouts, as you have already implemented. And I think this is the better way to solve the problem and never trying or even thinking to create different views for each orientation 🙅🏿♂️.
Attending the conditions:
The first condition only needs to set the axis property accordingly.
The order of the arrangedSubviews is part of the design, and therefore, its up to the developer to rearranged them manually if he/she has to.
In this part what I would do is what you have said: to removeFromSuperview() the button and addSubview(view:) from one subview to another.
This is made automatically, as long as we activate the constraints for one orientation and deactivate the other ones, the system update the UI without any problem.
The most important thing is to make sure that when removing subviews, any constraint attached to it is removed, or the app will crash.
I have been creating an application for iPhone and iPad. I am using Auto Layout (wAny and hAny). Now I want a separate design for iPhone 4s alone. How can I use separate designs for this device. I already completed most of the designs with this wAny and hAny. How can I change this.
Edit:
I want to change only few view controller not all the designs.
I suggest not to go with different storyboards. You can add 2 views inside that viewcontroller's(for which the design is different) view and toggle it programmatically depending on the device. Regarding autolayout, set wAny and hAny and add constraints accordingly.
VC.view
-iPhone 4 View
-Other device's view
This can be done in storyboard only.
So programmatically when loading the vc, check the device and show the specific view hiding the other view. In this case in future, even if the design is normalized, you can easily use the same view with change in one line of code.
This is necessary if the design is totally different. Or if it's just few sub views which are different, I think you should write some code to hide and unhide the subviews acc to the device.
I am a novice in iOS, please correct me if I am wrong anywhere.
Better to go with design it as separate controls if you have design changes and load it conditionally for 3.5 inch screens . If its a simple changes (easily managed through codes) then go with codes itself.
So I have a long form with 11 UITextViews. It's just long enough exceed the iPhone older 3.2" screen so I had to throw it all in a UIScrollView. Now when I rotate to horizontal the UITextViews won't resize to fit the newly available space to the left.
Any ideas about how I can get around this?
First, do you mean UITextFields? (instead of TextViews)
There are many different ways to go about this.
First of, did you use Interface Builder to build the view?
If the view is simple, you can try the elastic positioning provided by Interface Builder, you might have to fiddle with different options.
Another way is to use Autolayout system, available in iOS 6.0+
Or, if you're comfortable with handling frames yourself with codes, you can have different frame sizes set for when the view has rotated.
Or, you can create a separate xib file just for the landscape view and have the program load that xib when the phone rotated.
All of the above are widely used methods for handling rotations, you should choose what fits best in your situation.
I have setup a custom view with two subviews and a button. I am trying to understand CGRect better and work out what should be used for heights/widths and how to center items correctly. I imagine that using exact numbers like this:
UIButton *facebookLoginButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 300,75)];
... is not the correct way to complete this. When the device is rotated nothing fits to screen anymore.
I would also like to know how to not allow rotation on one view controller. For example a setting which I can stop rotate doing anything with the views, then later in the app rotation will be used again.
I have had a look through the design apple documentation but not sure exactly what I am looking for. I am looking for best practice for setting bounds/center items/sizes(width/heights)/working with multiple sub views and how they layout when programatically creating the views.
You can check for the device orientation and then adjust the sizes regarding to that.
[UIDevice currentDevice].orientation
If you're using iOS6 you can take a look at constraints. Or just use the interface builder, where it's pretty simple to manage that stuff (if you don't need to make it programmatically).
For portrait / landscape orientation, check this out:
Alternate landscape triggered at unwanted view
With that I managed to perform a landscape rotation only on one view controller while all the rest of the app stays in portrait (but you can adopt for your needs of course).
I want to minimize the amount of code I have to write, and use storyboards in xcode to specify the way the view should appear when in both portrait and landscape views.
What is the best/recommended way to do this that minimizes code? I've done some research, but am having trouble finding a simple solution..is it necessary to do some conditional segues, and re-hook up everything in my landscape view, or is there a simpler solution? Thanks!
Generally you define the autoResizingMask (or go to the size inspector in Interface Builder, as shown below) so that the controls will move or resize as the screen size changes. If you do that, you'll generally have pretty decent support for both landscape and portrait. You'll only have to do programmatic changes to the controls' frames if you do some fairly significant changes on orientation changes (e.g. you want to shuffle the various controls around so that they are in very different positions with respect to each other when you change orientation or you want to load very different UIImages). But 90% of the time, autoresizing settings can handle simple moving/resizing/recentering of controls for you: