iOS Rotation with UITabBarController - switch controller out completely and smoothly - ios

I have an iOS application and the main entry point into the storyboard is a Tabbar with with tabs. I want to support rotation but in landscape mode, each tab will look drastically different to the point I need to change the views out with others from the storyboard. At first though, I considered just switching out the entire tab bar controller when the user rotates, but I don't see how that might be accomplished. So I have two options that I can't seem to get anywhere with.
Switch each view with a segue somehow into it's landscape alternative and back. I've seen this done easily with modal views, but not with UITabbar before.
Switch out the entire tab bar somehow from the delegate so that I just have two completely separate section of my storyboard that are alike except one path is portrait and the other is landscape.
Does anyone have anything similar they are doing and could throw me a bone?

You can create a custom class for both view controllers, link them together with segoes, and then use didRotateFromInterfaceOrientation: to trigger the segues from code.
Create a class for your VC's. Add this code to the .m file:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[self performSegueWithIdentifier:#"rotateToPortrait" sender:nil];
} else {
[self performSegueWithIdentifier:#"rotateToLandscape" sender:nil];
}
}
And in your storyboard, create segues between the two views. Make their identifiers "rotateToPortrait" and "rotateToLandscape", respectively. The code you added will switch the views whenever the device is rotated.
EDIT: I think I misunderstood the question. If you want to move views around, change their size, etc. when the screen is rotated, while keeping the same navigation/tab bar state, then you can do something like this in the didRotateFromInterfaceOrientation method:
if (fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
myView.frame.origin.x = aNumber;
myView.frame.size.width = anotherNumber;
// Changing the layout of the views here by resetting their origins and sizes.
// This code is called when rotated from portrait to landscape.
} else {
// Do the same thing as above, but this one handles rotation from landscape to portrait.
}

Related

interface orientation not correct in presented view controllers in iOS 8

in iOS 7 and earlier, I was able to make UI changes in viewDidLayoutSubviews like so:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if ( UIInterfaceOrientationIsLandscape(self.interfaceOrientation) ) {
//update views for landscape
}
else {
//update views for portrait
}
}
I can still do this in iOS 8 except in view controllers that are presented by other view controllers. When a view controller is presented by another view controller, this does not work, because the self.interfaceOrientation property is not correct in the presented view controller. It does not reflect the current orientation, but rather the orientation right before the device rotation.
The issue is not present if presenting a view controller on iPad with modalPresentationStyle set to UIModalPresentationPageSheet. In other words, the issue is only present when presenting a full screen view controller.
Any suggestions?
Try using this instead:
[[UIApplication sharedApplication] statusBarOrientation]
Also, if you are dropping support for iOS 7 and going 8-only, I recommend you drop interface orientation handling in favor of trait collections and size classes, if you can.

iOS Sizing UITableView During Orientation Change

I have a view that has two tables. In the story board, I have two separate views, one horizontal and the other vertical. When I need to navigate to the view, the code detects the orientation and brings up the appropriate view (and does so on an orientation change.
I have the following code in my method:
-(void)viewDidAppear:(BOOL)animated{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight){
if(tableHeight2 > 324){
tableHeight2 =325;
}
table1.frame = CGRectMake(table1.frame.origin.x, table1.frame.origin.y, table1.frame.size.width, tableHeight1);
table2.frame = CGRectMake(table2.frame.origin.x, table1.frame.origin.y + 20 + tableHeight1, table2.frame.size.width, tableHeight2);
}else {
if(tableHeight2 > 500){
tableHeight2 = 500;
}
table1.frame = CGRectMake(table1.frame.origin.x, table1.frame.origin.y, table1.frame.size.width, tableHeight1);
table2.frame = CGRectMake(table2.frame.origin.x, table1.frame.origin.y + 50 + tableHeight1, table2.frame.size.width, tableHeight2);
}
}
This works wonderfully when I press a button to navigate to the view. It adds up all of the cell heights and makes the first table the appropriate height, then moves the second table 50 pixels below the first table. It also makes sure the second table doesn't extend beyond the visible screen area.
When the orientation changes, I the following code is executed:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration {
InitViewController *ini;
ini = [self.storyboard instantiateViewControllerWithIdentifier:#"Init"];
ini.location = MenuName;
[self presentViewController:ini animated:NO completion:nil];
}
This should do the same thing that pressing a barbuttonitem does: change to InitViewController while sending the StoryboardID to it in the ini.location variable. The code for the navigation buttons is pretty much identical to the code in willAnimateRotationToInterfaceOrientation. InitViewController then determines the orientation and sends the app to the correct storyboard UIView.
It does send it to the right view, I can tell based on the table widths. What it doesn't do is change the height of the first (top) table, table1. The first table retains the size it was given in the storyboard.
If there is area of code you think I need to post to get a better picture, let me know I'll be happy to add it. Any help, insight, or even just trial-and-error suggestions would be appreciated.
*Note: I have tried to change willAnimateRotationToInterfaceOrientation to ViewDidLayoutSubviews, to not effect.
Well, it seems a very small change fixed it. I noticed that the code on the navigation buttons had YES under "animate" for the view change, and the willAnimateRotationToInterfaceOrientation "animated:NO". I changed it to "YES" and that fixed it. Not sure why yet, perhaps it affects how the method displays the view or affects the load order, but there it is.

Interface Orientation with TabBarController

I am using a Tab Bar Controller in my app. In the most part of the app's behavior we have one single orientation (interfaceOrientationPortrait). But i have a view that runs a video in WebView. When i am running this video, the orientation remains portrait. I want to put for all orientations.
Well, i used the return type YES in my Video's class. Nothing has changed. I changed the return type to YES in my RootViewController class. Nothing has changed.
I would like to change the orientation only for the Video.
View controllers that are part of a tab bar controller won't rotate to an orientation if any of the tab bar controllers can not rotate to that orientation (at least if the tab bar is visible). So maybe you want to update all your controllers' method in order to let the rotation happen if the web view controller is visible on the tab bar controller.
If you need a deeper explanation, just ask. Good luck!
Edit (example code)
This is what could be your rotation methods for your tab bar controller view controllers:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ((self.tabBarController.selectedIndex == kMyWebViewControllerIndex))
{
return YES;
} else
{
return (orientation == UIInterfaceOrientationPortrait);
}
}
Is your web view in a view controller inside the tabBarController?
Try showing it in a modally presented view controller, it should work

Cannot resize AdMob's view upon orientation change

What I tried so far is, in viewDidLoad, I called
self.bannerView.autoresizingMask=UIViewAutoresizingFlexibleWidth;
and
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)newInterfaceOrientation duration:(NSTimeInterval)duration {
if (newInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || newInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
self.bannerView.frame=CGRectMake(0.0,
0.0,
480.0,
GAD_SIZE_320x50.height);
}
// Position the UI elements for portrait mode
else {
self.bannerView.frame=CGRectMake(0.0,
0.0,
GAD_SIZE_320x50.width,
GAD_SIZE_320x50.height);
}
}
Both of these didn't work for me.
Hmm, I don't think that AdMob's creatives can stretch to fit the size of the screen when in landscape. So despite the fact that you're stretching the frame of the view to fit, the ad itself I think will stay the same size.
This means you should still see an ad come in on orientation changes, it will just look like it's the same size (make sure to make another request for an ad in the willAnimateRotationToInterfaceOrientation: method to see this).
You don't need to do any moves, but you must set correct rootViewController for adMovView.
If you use view controller model please add line in each custom view controller
adMobView.rootViewController = viewController;
where viewController - root view controller of your app.
Do not code like this
adMobView.rootViewController = self;
in custom view!

Why won't my views rotate?

I have a Tab Bar application for iPad, created using the basic Tab Bar template. I have added some custom view controllers (one for each tab, each with a corresponding NIB) and also some extra view controllers with NIBs to be used as modal views. Everything works great until I rotate the device.
My app only supports portrait orientation, so I had this in all my view controllers:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIDeviceOrientationLandscapeLeft) &&
(interfaceOrientation != UIDeviceOrientationLandscapeRight);
}
However, the app would not rotate in the simulator or the device when turned upside down. I double and triple checked that all my view controllers had the above code.
I went through all my NIBs and checked that they all have "Rotate Subviews" ticked. I haven't changed any of the NIB settings from the defaults anyway, apart from the basic things needed to get them showing in the tab views.
I tried changing the code in all my view controllers to this:
- (BOOL)shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
It made no difference. I have made absolutely sure that the same method is being used in all the view controllers. I don't know what else I can do. I can see no reason why it shouldn't rotate to the upside down view.
Any help with this would be much appreciated.
Got it! One of my View Controllers was not hooked up to the relevant tab in IB. As I hadn't added the images or written the code for that View Controller yet, I didn't notice that it wasn't associated in IB. I had done the shouldAutorotateToInterfaceOrientation method, but it seems that didn't take effect until the connection was made in IB.
Thanks very much for suggestions on this. That's a highly frustrating problem now dealt with!
Also, this is Apple's very helpful guide: http://developer.apple.com/library/ios/#qa/qa1688/_index.html
In my case - I forgot to call self = [super initWithNibName ....]!
Does "all your view controllers" include the Tab Bar Controller?
In tab bar apps that is the only view controller who's shouldAutoRotateToInterfaceOrientation is called and evaluated at all.
The first snippet you have is logically incorrect:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
return (orientation != UIDeviceOrientationLandscapeLeft) &&
(orientation != UIDeviceOrientationLandscapeRight);
}
Here, orientation is an instance of UIInterfaceOrientation whereas UIDeviceOrientationLandscapeLeft is an instance of UIDeviceOrientation. The two are not the same type and so should not be compared.
Instead, you should use the UIInterfaceOrientation options:
typedef enum {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeRight
} UIInterfaceOrientation;
Change the method to
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
return (orientation == UIInterfaceOrientationLandscapeLeft ||
orientation == UIInterfaceOrientationLandscapeRight);
}
(the code seems to me more readable when put in the affirmative rather than negative)

Resources