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

更新2

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

-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; } 

现在,每当我select一个标签项目,设备旋转到肖像模式完美。 但是,现在我可以在select(a)的同时旋转设备,设备将旋转到横向模式。 我怎样才能停止设备旋转?

我相信这个方法在我的选项卡控制器子类是什么导致这一点:

 - (BOOL)shouldAutorotate { if(self.selectedIndex == 0) { return NO; } return [self.viewControllers.lastObject shouldAutorotate]; } 

如果我返回“否”,我不能旋转,当我在视图控制器中,但是当我select它,它不会自动旋转到肖像。 如果返回“是”,则可以在视图控制器中进行旋转,但是当select它时,会自动旋转为纵向。


我有一个自定义选项卡栏控制器在我的应用程序与以下层次结构:

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

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

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

 - (BOOL) shouldAutorotate { return NO; } - (NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } 

UPDATE

我已经添加了这个视图控制器(一),但我在我的看法中间有一个黑色的方块,导航栏中的标题不再居中。

 -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; } 

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

它工作的很好,直到你切换到另一个标签,而在这个特定的选项卡不支持的界面方向。

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

注意:使用attemptRotationToDeviceOrientation将界面旋转到设备方向时,从仅肖像选项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&#x4E0A;

对于这个确切的问题,我使用了一种解决方法。 这个想法是UITabBarController并将其delegate设置为自己。 然后在一个子类中,我做了一个下面的“黑客”:当只select肖像控制器时,我推动并立即解除一个空的模态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]; } } 

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

编辑:你也应该在UITabBarController子类中实现supportedInterfaceOrientationsshouldAutorotate 。 你应该在视图控制器中的-shouldAutorotate中返回YES ,以保持肖像。 否则,在标签栏中select时,它不会从风景旋转到纵向。

 - (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; } 

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

 - (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; } }