views:

1562

answers:

3

Hi,

I'm having a real issue with UITabBarController. The outcome I'm after is the following: 1) in portrait mode, a simple tab bar based application (with navigation bars) nothing too fancy. 2) in landscape mode, I want to use my own UIViewController ignoring the UITabBar completely.

The approach (I tried many variants) I tried last which I fail to understand why is not "working" is the following:

  • I have a custom UIViewController (Call this AA) that is suppose to manage "everything".
  • This controller is added to the window in application start and in its loadView creates two controllers: a UITabBarController (Call this TBC) and a UILandscapeController (Call this LSC). then I add the tabbarcontroller view as a subview of AA's view.
  • now in AA class I override the didRotate blah or willRotate blah and basically want to switch between the two views, by this I means something like: (pseudo code): going from portrait to landscape:
  • [TBC.view removeFromSuperView];
    [AA.view addSubview:LSC.view];
    

    and when returning to portrait reverse it.

    [LSC.view removeFromSuperView];
    [AA.view addSubview:TBC.view];
    

    The amount of problems I have (well, it simple rotates wrongly creating a real messed up interface) are something completely unexplained. It seems like the tabbarcontroller view does not "like" at all to be in the standard view heirarchy but rather it wants to be attached directly to the screen. I wonder what is the best approach to achieve my goal and why the tabbar does not like to be a subview of a view,

    any hints mostly appreciated.

    -t

    +1  A: 

    Check out the UIViewController instance method rotatingFooterView in the docs.

    Or, you may manage TabBar by yourself, not through the UITabBarController.

    naoki
    Thanks for the tip! however I don't understand why my suggested approach is not working. I'm sure there must be a way to create an interface as I seek, its pretty basic. I'm missing something simple. I don't think this problem requires creating a complete TabBar manager. Any other suggestions?
    Tzur
    +1  A: 

    Your problem comes from the typo, I think. Change removeFromSuperView to removeFromSuperview. Though, it still has a problem. Tab bar doesn't rotate properly. It go upwards till it disappers.

    How about not removing the tab bar, and make it transparent.

    naoki
    A: 

    Just in case you still need the answer, or someone else stumbles onto this, I've done the same thing and got it working, but there are a couple of hoops you have to jump through. In order to rotate a UITabBarController's view, there are four things you have to do:

    1. Remove the status bar before switching to the view
    2. Rotate the view to the new frame
    3. Add the status bar back to the view
    4. Switch to the view.

    I've got a RootRotationController that does this that looks like this:

    @implementation RootRotationController
    
    #define degreesToRadian(x) (M_PI * (x) / 180.0)
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        if ((UIInterfaceOrientationPortrait == interfaceOrientation) || (UIInterfaceOrientationPortraitUpsideDown == interfaceOrientation)) {
            [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
        }
        // Return YES for supported orientations
        return YES;
    }
    
    - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
        [super willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:duration];
        if (UIInterfaceOrientationLandscapeLeft == interfaceOrientation) {
            self.view = self.landscape.view;
            self.view.transform = CGAffineTransformIdentity;
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
            self.view.bounds = CGRectMake(0, 0, 480, 300);
        } else if (UIInterfaceOrientationLandscapeRight == interfaceOrientation) {
            self.view = self.landscape.view;
            self.view.transform = CGAffineTransformIdentity;
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
            self.view.bounds = CGRectMake(0, 0, 480, 300);
        } else if (UIInterfaceOrientationPortrait == interfaceOrientation) {
            mainInterface.view.transform = CGAffineTransformIdentity;
            mainInterface.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
            mainInterface.view.bounds = CGRectMake(0, 0, 300, 480);
            [[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
            self.view = mainInterface.view;
        } else if (UIInterfaceOrientationPortraitUpsideDown == interfaceOrientation) {
            mainInterface.view.transform = CGAffineTransformIdentity;
            mainInterface.view.transform = CGAffineTransformMakeRotation(degreesToRadian(180));
            mainInterface.view.bounds = CGRectMake(0, 0, 300,480);
            [[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
            self.view = mainInterface.view;
        }
    }
    

    In addition, you should know that shouldAutorotateToInterfaceOrientation is called just after adding the root controller's view to the window, so you'll have to re-enable the status bar just after having done so in your application delegate.

    Douglas Mayle