In my app I have a tabbar with 5 buttons. The total app has only portrait orientation and I have set it correctly.
My problem is that when I click the second button of the tabbar, the view appears normally in portrait but when the user tilts the device I want that particular view to be get changed to landscape. Is it possible to change the tabbar position to landscape and when the other buttons are clicked all to be changed to portrait?
Else while it is tilted I have to show the view alone in landscape without the tabbar, how can I do this?
So, to be clear, you want the entire app and all views in portrait EXCEPT for the view triggered by the second tab bar button, which you want to always appear in Landscape?
if I've not confused your question, than just put the following line of code in the "viewDidLoad" method of the controller of view number 2
self.view.transform = CGAffineTransformMakeRotation(M_PI / 2);
You probably want to bite the bullet and let your project accept multiple orientations at its highest level and then decide per UIViewController which orientations are supported. This will allow the frameworks to take care of a lot of the work for you (always a good idea).
In each view's controller, override this method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
You will want to return YES for any orientation that you want the view to support.
The four options for the interfaceOrientation parameter are:
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
So for your case, you will want the view controller hosting your view and tab bar to support all of the orientations. This is how the function would look:
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return YES;
}
But for a extra detail, if you wanted to support only Landscape Left and Portrait Upside Down orientation, the function would look like this:
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
A UITabBar only supports rotation, if the ViewControllers of all tabs return YES at shouldAutorotateToInterfaceOrientation.
You could achieve what you want, if you let your "portrait" tabs check if they are visible (via
tabbar.selectedViewController
or
tabbar.selectedIndex
and only reply yes when they're not selected.
The user experience could be confusing though, when the user changes the tab in landscape mode
a portrait view is presented ...
try this w.r.t.: tabbar.selectedViewController
[[UIDevice currentDevice] setOrientation:UIDeviceOrientationLandscapeRight];
Related
In my app i have added tabBarController in split View's RootViewController.In that portrait mode works fine but it orientation doesn't change to landscape mode. Orientation doesn't change in landscape when i add tabBarController in rootViewController.
Please suggest me the way to do this.
Make sure that all your view controllers contained in the tab bar controller can be display in all orientations. see Technical Q&A QA1688 for more informations. https://developer.apple.com/library/ios/#qa/qa1688/_index.html
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
I've got my View hierarchy set up like this.
UITabBarController
|
UINavigationController
| |
| UIViewController
|
UINavigationController
|
UIViewController
The thing is that I have a ViewController that is only shown in Portrait, as soon as I turn the device to landscape another ViewController is being pushed on top, that is working as intended so far.
What I want now is that as soon as I push the back button on the newly popped ViewController that the old ViewController is being forced to Portrait, even though the Device is still in Landscape.
I have tried it with transitions, but then the other views are getting screwed and don't properly recognize there orientation anymore leading to a mess of displaced views.
The only thing that worked for me was using
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
in my ViewController and presenting it with presentModalViewController.
This forces the View to stay in landscape.
Not exactly what I wanted, but it worked out.
Try adding this to your original view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) return YES;
return NO;
}
This should force it to only display in portrait orientation.
The code below will force the view into landscape mode, but only if the parent view controller supports landscape mode.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
If the parent view controller of the view you want to force into landscape mode is portrait only, you'll have to create a new new navigation controller. The easiest way to do that is just presenting the forced-landscape view controller in a modal view. So use presentModalViewController instead of pushViewController.
I am trying to have every viewController to display different layout depending on the screen orientation?
What is the best way to move items around?
Manually change the location of items (Write code to do that)?
Have 2 nibs 1 for each orientation? (Is it even possible to switch nibs?)
Please explain
If it is feasible with your layout, I would make it in code. That way if you have any static elements that are on both layouts you can take advantage of the rotating animation.
If it is not feasible to do this, you can use two use by using a subview. Have 3 xibs. Your main one with any elements on both orientations. Have a view inside this view, and load from two other xibs portrait and landscape layouts.
Yes - use willAnimateRotationToInterfaceOrientation:duration:
You can use loadNibNamed:owner:options: as described here
It would be best to have two different XIB files. Here is some code:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
//show portrait XIB here
} else {
//show landscape XIB here
}
}
Ok I have an interesting issue on an iPad application I am developing.
When the app launches in portrait mode the layout works as expected. I rotate the iPad and the rotation works fine.
When the application launches in landscape mode there is additional white space appearing and the layout does not work as expected. But when I rotate the application to portrait it rotates just fine. It also lays out fine when I rotate it back to landscape.
What could be causing this problem? The view controller in question is a view controller that contains a UINavigationController (I had to add in a header). I wonder if it is something with UINavigationController.
Your view is expecting Portrait mode upon launch. In your view Controller, you need to let it know to look for orientation, and load the corresponding view.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight))){
self.view = landscape;
}else if(((interfaceOrientation == UIInterfaceOrientationPortrait) ||
(interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))){
self.view = portrait;
}
return YES;
}
Ok so what was strange in my application is that the layout would become correct when the tab controller switched tabs back to the view that was being funky. So, I added a hack in order to switch between the tabs before the makeKeyAndVisible of the main window.
I did try your suggestion WrightsCS. The real reason it didn't work is because I'm loading UINavigationController's view in the sub view of the page, so I didn't really have control of the layout that was messing up. The top bar of the navigation controller was loading a little lower than it should have been.
i have got 2 GUIs and 2 Controllers
1 is called landscapeguicontroller and the second is called highguicontroller.
Now generally i call the highguicontroller, and when i rotate my iphone it detects that and then it shows the landscapeguicontroller:
Code:
landscapeguicontroller *neu =[[landscapeguicontroller alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:neu animated:YES];
[self dismissModalViewControllerAnimated:YES];
The Problem is that then the animation pushes the new window from the beyond side of the iphone up into the window.
In the Landscapeguicontroller,i have added to the the following lines:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
when i want go back to the highguicontroller i call:
[self dismissModalViewControllerAnimated:YES];
that all works , but just in the second animation i see the correct "rotation animation".
Have you got any suggestions?
So a short Problem description:
in the 1. animation from high to landscape, the landscape is pushed into the window
BUT in the 2. animation from landscape to high, the rotation looks like a real rotation...
i want the 1.animation look like the 2. animation
best regards
Ploetzeneder
To avoid "The Problem is that then the animation pushes the new window from the beyond side of the iphone up into the window.", try setting the view controller's modalTransitionStyle property to one of the following, whatever you prefer:
typedef enum {
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
} UIModalTransitionStyle;
Also, if you want to avoid the animated rotation, you can set your shouldRotate... method to disallow other orientations, but then set up to receive notifications when the device physically changes orientations, and present your modal viewcontroller when in the appropriate orientation for it. See Apple's "AlternateViews" sample code for an example of this.
The notifications reflect the physical orientation of the device, and you can receive them whether the interface is allowed to change or not. (You can look at the UIApplications's statusBarOrientation property to see what orientation the UI is in).
It sounds like you want the sequence to go like this:
Physically rotate the device from portrait to landscape
Animate the portrait view (highguicontroller) to landscape
Push the landscape view (landscapeguicontroller) up from the new "bottom" of the screen
If that's right, you'll need to have something like the following in your highguicontroller implementation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
}
This will take care of step 2 (it will rotate the portrait view to landscape in either direction).
Then you'll want something like this:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if(fromInterfaceOrientation == UIInterfaceOrientationPortrait) {
[self presentModalViewController:landscapeguicontroller animated:YES];
}
else {
[self dismissModalViewControllerAnimated:YES];
}
}
That should present the landscape view after the rotation animation is complete and then dismiss it after the device is rotated back to portrait.
Hope that helps!