I'm using storyboards and need to create to different views for portrait and landscape layout. I can't use auto layout in this case because I need to completely rearrange things in some cases.
I found a solution to use two different views and hide or show it depending on the device orientation but it doesn't work very good for me. I have a lot of outlets that I need to connect from xcode designer to code, and it seems that I can't connect two diffrents objects like for example two different buttons to the same IBOutlet. Can I? When I did this only one was really working. Moreover this solutions doesn't seem so efficient.
I took also a different approach and created two different view controllers which I load according to the device orientation, but there's a problem when for example I turn off application change orientation of the device and turn on it again and come back to a view controller that was in the beginning of the navigation stack, then it has an orientation that it has before.
Anyone has some ideas how to solve this problem?
You should only use one ViewController and one view and kind of hard-code the positions of the elements. Like (pseudocode)
if (orientation landscape)
label1.frame = ...
else (orientation portrait)
label1.frame = ...
Maybe you can group parts of the layout within another UIView (select the elements and go in Xcode->Editor Menu->Embed->View. Then connect the new view to the ViewController and push it where you need it.
Take a look at this answer, maybe it helps
Related
To put it simply, my app has two main views: the first serves to choose some values, the second displays a report. Both are TableView based.
The app looks well on iPhone with any screen size and for any orientation, but since the app’s thought to be universal, I want to get rid of those gaps between elements when the app runs on iPad.
I decided to have the app displaying both views on iPad screen simultaneously as official YouTube app does:
(1) and (2) are the first and the second View controller.
I see it this way:
1) Some initial view controller (additional navigation view controller?) checks idiom (iPhone / iPad) and chooses the next viewController. If idiom is iPhone, the first view controller is pushed.
2) If idiom is iPad, the «new» view controller is pushed. It has two view containers containing the fist view and the second view. Containers have autolayout constraints etc.
Questions:
1) Is it a right idea in context of Apple app design philosophy? What’s the better way to create iPad view combining existing ‘iPhone’ views?
2) Where to check for device type? Shall I use the second storyboard or something? Maybe there’s a good tutorial for this case, I didn’t find one.
Thanks in advance!
For the 2nd part of your question I think you want to look into
I think you want to look into Size Classes and Auto Layout
You can make a single view but depending on the size / orientation of the device - you can enable/disable certain components of the view.
You can pin views so that in portrait you have your 1st layout and in a landscape you have your 2nd layout.
With regards to your 1st question - you do have the ability to embed a view inside of another view
I'm not sure if this is what you are looking for - but as far as what apple is pushing I believe size classes is what they "suggest". You can do a lot. The only thing is make sure you turn on the assistant editor into storyboard preview mode it will help a lot.
I know 'best practices' are a stackoverflow taboo, but i'm giving it a shot anyhow because I think this important and demands a specific answer. Auto layout is new and, with the recently announced iPad side-by-side multitasking, auto layout nuances have never been more important to understand.
My situation: My app will have two lists. On the iPhone, they will only be viewed one at a time. I can achieve this:
With one ViewController that can toggle between two arrays of list data.
With two ViewControllers, each with their own tableView and data
With one ViewController and two tables, but one always hidden
Better option?
My specific problem: On the iPad I want both lists to be shown side by side, simultaneously. Both the iPhone and iPad will run the app only in portrait (landscape will not be supported) I see a few options for supplying the side by side view:
Not sure how to make side-by-side work with option #1, except to programmatically add a second table for the iPad layout
The two VCs from the iPhone version would appear side by side for the iPad version, using a previously hidden container view to add VC2 to VC1
Both tables visible at once
Better options?
I would greatly appreciate an answer as to how to achieve this functionality. Although I understand the concepts for each option, I do not understand the specific steps/code, so a thorough explanation would be appreciated. Thank you.
I had this exact scenario in my app and I used Option #2.
For iPad, it'll be using the w-Regular h-Regular size class.
This site has a great visual and explanation of size classes.
While in Interface Builder, switch to the w-Regular h-Regular size class.
While in w-Regular h-Regular, drag out a Container View from the Object Library (bottom right corner in Interface Builder) and place it in your view.
While in w-Regular h-Regular, set your constraints as you need them to take the Container View into consideration in the new layout.
Existing constraints may need to be turned off. You can do so in the Size Inspector while in the constraint. Note in the image below that my constraint is installed. Click the + to the left of the Installed checkmark to uninstall it in the w-Regular h-Regular size class.
Another way to uninstall a constraint is by highlighting the constraint while in the Size Inspector for your screen object and pressing delete. It doesn't actually delete the constraint, it simply uninstalls it from the current size class.
Link the VC to the Container View. ctrl-drag from Container to VC to create an embed segue. You'll also want to add code to only use this embed segue while on an iPad. Give the segue an identifier by selecting the segue in IB and going to the Attributes Inspector. In my example code below I called the segue EmbedSegueName.
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && [identifier isEqualToString:#"EmbedSegueName"]) {
return YES;
}
return NO;
}
Don't allow access to the second VC. I don't know how you're displaying the two different VCs on the iPhone, but in my app I was using UITTabBarController. This is how I removed the extra VC from the iPad's tab bar in my application.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// Remove the tab bar item because it will be contained in the iPad's layout.
// In this example, it's removing the 2nd tab bar item.
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[self.tabBarController viewControllers]];
[viewControllers removeObjectAtIndex:1];
[self.tabBarController setViewControllers:viewControllers animated:YES];
}
Tip: If you run into errors running the iPhone version and it's complaining about the container view (even though it's not installed on the iPhone's size classes), try putting the Container View into another view and see if that resolves the issue.
I hope this is enough to get you started.
What is the general pattern for supporting a different display on a VC rotation?
Would I create a new VC in interface builder, design it, etc.. Then on willRotate, segue to it? Or what is the proper way to handle this?
Example, tableview in portrait.
Rotate left, and now show a graph
I eneded up adding a different view controller designed sideways. Then I used the rotation delegate methods to figure out when something rotates to make the move.
I am making an iOS app (iPad) that has a very complex layout. I could try to use Auto Layout to accomodate orientation switching, but it's simply to complicated. I would like to have two seperate nib's, one for each orientation.
So here's the question: How do I convert an app using Storyboards to use Nibs/Xibs?
Don't do this unless you really think that you have to. I takes a very long time. With that said, I've been dumb enough to try this a few times, and you really have to edit a lot of code from being segues, to loading up the view controller along with it's NIB name, and then copy all of your designs for each respective view into it's respective NIB.
Good luck!
A better solution might be to have also a copy of your landscape view in storyboards and then switch between the view controllers when rotation occurs to landscape etc.
You can register for rotation events.
I want to have multiple views in my application that I switch between.
What is the proper way to switch between UIViews that also supports UISplitViewController?
Is there a support way to switch or are Apple's controller classes designed to be root and root only?
I've tried having one root view and root controller and swap subviews in and out. One of the subviews is a UISplitViewController. It did not like the arrangement and does not display correctly. The detail view was not displayed, the master view displayed wrong orientation and wrong size.
I've then tried managing adding and removing one subview from the UIWindow in the app delegate. This works most of the time. However, the views added after the applicationDidFinishLaunching method do not appear setup correctly. They mostly look correct, however sometimes the orientation thinks its portrait when in reality its landscape. Also, when I try to display a popover, it shows up in an incorrect location. If I change the orientation, it redraws correctly. I've also have some random instances where the UISplitViewController view does not fully display, as if its frame is incorrectly sized.
Any suggestions heartily appreciated.
In applicationDidFinishLaunching, your objects haven't completed loaded from NIBs yet. Try using a viewDidLoad method instead.
What is the user-interface for switching between views? If one of these views represents a transient mode that the user enters and then exits, consider using a modal view. (See presentModalViewController:animated:.)
I would need more details about what you're doing to answer more particularly.