Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
673 views
in Technique[技术] by (71.8m points)

ios - TabBarController rotation problems

All week I have been searching SO for a solution to my unique problem, but nothing has worked for me yet. I have a TabBarController that has 6 tabs. iOS automatically creates the "More" tab, which contains the view controller,"Dashboard", that I am having difficulty with. The "Dashboard" view controller is acting as a page controller that has 3 pages.

When I press the "Dashboard" item, I want the screen orientation to change from Portrait to Landscape. I've learned through countless other SO posts that rotation is controlled from the parent TabBarController. I have also learned that the "More" tab is actually a navigation controller, which adds some more complication to the mix.

To reiterate and be direct, when I press the "Dashboard" tab in the TabBarController's "More" tab, I want the screen to change its orientation from Portrait to Landscape.

And YES, I have already tried this: [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationLandscapeLeft]forKey:@"orientation"]; and it didn't work.

I've also tried overriding every function in the TabBarController and MoreNavigationController that has to do with rotation and orientation, as well as in the child views. I will post my TabBarController below. Any help will be appreciated, thanks.

TabBarViewController.h:

@interface TabBarViewController : UITabBarController<UINavigationControllerDelegate>{}
@end

TabBarViewController.m:

@implementation TabBarViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.moreNavigationController.delegate = self;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if([self.selectedViewController isKindOfClass:[Dashboard class]])
    {
        return UIInterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskAll;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return YES;
}

- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController
{
    if([tabBarController.selectedViewController isKindOfClass:[Dashboard class]])
    {
        return UIInterfaceOrientationMaskLandscape;
    }

    return UIInterfaceOrientationMaskAll;
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{

    NSLog(@"tabBarController didSelectViewController = %lu", (unsigned long)tabBarController.selectedIndex);

}

- (NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
{
    if([navigationController.topViewController isKindOfClass:[Dashboard class]]
       || [navigationController.topViewController isKindOfClass:[ViewController1 class]]
       || [navigationController.topViewController isKindOfClass:[ViewController2 class]]
       || [navigationController.topViewController isKindOfClass:[ViewController3 class]])
    {
        return UIInterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

- (UIInterfaceOrientation)navigationControllerPreferredInterfaceOrientationForPresentation:(UINavigationController *)navigationController
{
    NSLog(@"navigationControllerPreferredInterfaceOrientationForPresentation");
    if([navigationController.topViewController isKindOfClass:[Dashboard class]]
       || [navigationController.topViewController isKindOfClass:[ViewController1 class]]
       || [navigationController.topViewController isKindOfClass:[ViewController2 class]]
       || [navigationController.topViewController isKindOfClass:[ViewController3 class]])
    {
        return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
    }
    return UIInterfaceOrientationPortrait|UIInterfaceOrientationMaskLandscapeRight|UIInterfaceOrientationMaskLandscapeLeft;
}

- (void)navigationController:(UINavigationController *)navigationController
      willShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animated
{
    if([viewController isKindOfClass:[Dashboard class]])
    {
        [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationLandscapeLeft]forKey:@"orientation"];
    }
}

@end
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Changing the orientation of a UITabBarController

While there are dozens of maybe and try this for this problem, the main issue reside in the careful design of each UINavigationController, a proper response to supportedInterfaceOrientations in the UITabBarController, and some code to enforce the desired orientation.

In all likelihood, this may just be an iOS bug, since once rotated, the UINavBarController and all embedded UINavigationController behave correctly.

The following statement is not true. Tab bar controllers do rotate.

TabBarControllers can't rotate


Setup orientation for each UINavigationController

Landscape example:

class HorizontalNavigationController: UINavigationController {
    override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
        return .landscape
    }
}

Portrait example:

class VerticalNavigationController: UINavigationController {
    override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
        return .portrait
    }
}

Defer TabBarController orientation to selected view controller

class TabBarController: UITabBarController {
    override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
        if let selectedViewController = selectedViewController {
            return selectedViewController.supportedInterfaceOrientations
        }
        return .allButUpsideDown
    }
}

Enforce the interface orientation change

This is the contentious aspect of UITabBarController. Somehow, the orientation change does not happen like it would in a UINavigationController, and needs a nudge.

To do so with the fewest amount of code, use an Object and subclass it into a TabBarControllerDelegate. You can do most of the work in Interface Builder.

class TabBarControllerDelegate: NSObject, UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        let orientedViewController = UIViewController()

        tabBarController.present(orientedViewController, animated: false) { () -> Void in
            tabBarController.dismiss(animated: false, completion: { () -> Void in
            })
        }
    }
}

Storyboard Structure

Using a Storyboard helps visualize the structure of the application as well as the relationship between all classes.

Storyboard


? Find this solution on GitHub and additional details on Swift Recipes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...