限制选项卡栏视图控制器中的旋转

时间:2014-11-26 04:53:53

标签: ios objective-c uiviewcontroller rotation uitabbarcontroller

更新2

在我的UITabBarController子类中,我尝试添加:

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

        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];

}

现在,每当我选择一个标签项时,设备都会完美地旋转到纵向模式。但是,现在我可以在选择(a)时旋转设备,设备将旋转到横向模式。如何阻止设备旋转?

我相信我的tab控制器子类中的这个方法导致了这个:

- (BOOL)shouldAutorotate {

    if(self.selectedIndex == 0)
    {
        return NO;
    }

    return [self.viewControllers.lastObject shouldAutorotate];
}

如果我回来'否'我在视图控制器中无法旋转,但是当我选择它时,它不会自动旋转为纵向。如果我回来“是”'我可以在视图控制器中旋转,但当我选择它时,它会自动旋转为肖像。


我的应用中有一个自定义标签栏控制器,具有以下层次结构:

UITabBarController
    |
    UINavigationController
    |  |
    |  UIViewController(a)
    |
    UINavigationController
    |  |
    |  UIViewController(b)
    |
    UINavigationController
       |
       UIViewController(c)

我希望视图控制器(a)只能在纵向模式下查看,而视图控制器(b)和(c)在所有方向上都可以查看,但是可以颠倒。现在,我可以单独为每个视图控制器执行此操作,但是当我处于横向模式(b)并选择(a)的选项卡项时,我的问题就出现了,然后以横向模式显示a,这看起来不像好。如何确保标签栏(或视图控制器)检查是否可以在当前方向查看要选择的视图控制器?

如果需要,这是我的代码(a)将其自身限制为肖像模式:

- (BOOL) shouldAutorotate
{
    return NO;
}

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

更新

我已将此添加到视图控制器(a)中,但我在视图中间看到一个黑色方块,导航栏中的标题不再居中。

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];


    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];


}

3 个答案:

答案 0 :(得分:5)

由于iOS 7.0 UITabBarController支持通过- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController转发方向。

它很有效,直到您在界面方向切换到另一个选项卡时此特定选项卡不支持。

不幸的是,tabbar控制器在这种情况下不会强制轮换,唯一的方法是使用私有API。

注意:当从仅纵向标签切换回支持任何方向的标签时,我使用attemptRotationToDeviceOrientation将界面旋转到设备方向。

这是我解决问题的方法:

static const NSInteger kPortraitOnlyTabIndex = 1;

@interface TabBarController : UITabBarController<UITabBarControllerDelegate>
@end

@implementation TabBarController

- (id)initWithCoder:(NSCoder *)aDecoder {
    if(self = [super initWithCoder:aDecoder]) {
        self.delegate = self;
    }
    return self;
}

- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController {
    if(tabBarController.selectedIndex == kPortraitOnlyTabIndex) {
        return UIInterfaceOrientationMaskPortrait;
    }

    return UIInterfaceOrientationMaskAllButUpsideDown;
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    [UIViewController attemptRotationToDeviceOrientation];

    if([self.viewControllers indexOfObject:viewController] == kPortraitOnlyTabIndex) {
        SEL sel = NSSelectorFromString(@"setOrientation:");
        if([[UIDevice currentDevice] respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [[UIDevice currentDevice] performSelector:sel withObject:(__bridge id)((void*)UIInterfaceOrientationPortrait)];
#pragma clang diagnostic pop
        }
    }
}

@end

我将示例应用程序放在https://github.com/pronebird/TabBarOrientationExample

的Github上

答案 1 :(得分:2)

我针对这个确切的问题使用过一次解决方法。我们的想法是将UITabBarController子类化并将其delegate设置为自身。然后在一个子类中我做了一个跟随“hack”:当选择了仅限肖像的控制器时,我推动并立即解除了一个空模态VC。它迫使iOS以某种方式设置正确的方向。

-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
    NSInteger currentViewControllerSupportsLandscape = ([viewController supportedInterfaceOrientations] & UIInterfaceOrientationMaskLandscape);
    if(UIInterfaceOrientationIsLandscape(currentOrientation) &&  !currentViewControllerSupportsLandscape) {
        //workaround to force rotating to portrait
        UIViewController *c = [[UIViewController alloc]init];
        [viewController presentViewController:c animated:NO completion:nil];
        [viewController dismissViewControllerAnimated:NO completion:nil];
    }
}

请注意,它可能取决于某些实现细节,并且可能在将来停止工作。

编辑:您还应该在supportedInterfaceOrientations子类中实现shouldAutorotateUITabBarController。并且您应该在视图控制器中的YES中返回-shouldAutorotate,以保持纵向。否则,在标签栏中选择时,它不会从横向旋转为纵向。

- (NSUInteger) supportedInterfaceOrientations {
    return [self.currentViewController supportedInterfaceOrientations];

}

- (BOOL) shouldAutorotate {
    return [self.currentViewController shouldAutorotate];
}

- (UIViewController*) currentViewController {
    UIViewController* controller = self.selectedViewController;
    if([controller isKindOfClass:[UINavigationController class]]) {
        controller = [((UINavigationController*)controller).viewControllers objectAtIndex:0];
    }
    return controller;
}

答案 2 :(得分:0)

它简单,创建UITabBarController的子类,并实现委托方法

- (BOOL)tabBarController:(UITabBarController *)tbController shouldSelectViewController:(UIViewController *)viewController {
    //Check for orientation here
    if (supported orientation for view controller == [[UIApplication sharedApplication] statusBarOrientation]) {
        return YES;
    } else {
        return NO;
    }
}