如何强制iOS 6中的UIViewController纵向
由于ShouldAutorotateToInterfaceOrientation
在iOS 6中已被弃用,我使用它来强制一个特定的视图只有肖像 ,在iOS 6中做到这一点的正确方法是什么? 这只是我的应用程序的一个区域,所有其他视图可以旋转。
如果您希望我们所有的导航控制器都遵守顶视图控制器,您可以使用一个类别,因此您不必经过并更改一堆类名称。
@implementation UINavigationController (Rotation_IOS6) -(BOOL)shouldAutorotate { return [[self.viewControllers lastObject] shouldAutorotate]; } -(NSUInteger)supportedInterfaceOrientations { return [[self.viewControllers lastObject] supportedInterfaceOrientations]; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation]; } @end
正如一些评论指出的那样,这是对问题的快速解决。 更好的解决scheme是UINavigationController的子类,并把这些方法放在那里。 一个子类也有助于支持6和7。
对于iOS6来说,最好的方法是在Ray Wenderlich团队的“iOS6 By Tutorials”( http://www.raywenderlich.com/)中注明,并且比大多数情况下的;UINavigationController
的子类更好。
我正在使用包含一个UINavigationController
设置为初始视图控制器的故事板的iOS6。
//AppDelegate.m – 这个方法在iOS6之前是不可用的
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{ NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown; if(self.window.rootViewController){ UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject]; orientations = [presentedViewController supportedInterfaceOrientations]; } return orientations; }
//MyViewController.m – 返回每个UIViewController
支持的方向
- (NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait; }
这个答案与OP的文章评论中提出的问题有关:
要强制视图出现在给定的方向,请将viewWillAppear放在下面:
UIApplication* application = [UIApplication sharedApplication]; if (application.statusBarOrientation != UIInterfaceOrientationPortrait) { UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; }
这是一个黑客,但这迫使UIViewController
纵向呈现,即使前一个控制器是风景
更新为iOS7
上面的方法现在已经被弃用了,所以对于iOS 7,使用以下方法:
UIApplication* application = [UIApplication sharedApplication]; if (application.statusBarOrientation != UIInterfaceOrientationPortrait) { UIViewController *c = [[UIViewController alloc]init]; [c.view setBackgroundColor:[UIColor redColor]]; [self.navigationController presentViewController:c animated:NO completion:^{ [self.navigationController dismissViewControllerAnimated:YES completion:^{ }]; }]; }
有趣的是,在撰写本文时, 无论是现在还是解雇都必须是animation的。 如果两者都不是,那么你会得到一个白色的屏幕。 不知道为什么这使得它的工作,但它! 视觉效果因animation而异。
所以,当我只显示肖像模态视图时遇到了同样的问题。 通常,我会创build一个UINavigationController
,将viewController
设置为rootViewController
,然后将UINavigationController
显示为模式视图。 但是对于iOS 6, viewController
现在会要求navigationController支持它所支持的接口方向(默认情况下,它现在全部用于iPad,而其他所有方面则完全颠倒)。
解决scheme :我不得不UINavigationController
并覆盖自动旋转方法。 有点跛脚。
- (BOOL)shouldAutorotate { return NO; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } // pre-iOS 6 support - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return (toInterfaceOrientation == UIInterfaceOrientationPortrait); }
IOS 5
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ return (interfaceOrientation == UIInterfaceOrientationPortrait); }
IOS 6
-(BOOL)shouldAutorotate{ return YES; } -(NSInteger)supportedInterfaceOrientations{ // UIInterfaceOrientationMaskLandscape; // 24 // // UIInterfaceOrientationMaskLandscapeLeft; // 16 // // UIInterfaceOrientationMaskLandscapeRight; // 8 // // UIInterfaceOrientationMaskPortrait; // 2 // return UIInterfaceOrientationMaskPortrait; // or return 2; }
我不同意从@aprato的答案,因为UIViewController旋转方法是在类别本身声明,从而导致未定义的行为,如果你重写,然后在另一个类别。 在UINavigationController(或UITabBarController)子类中重写它们更安全
此外,这不包括您从横向视图推送/呈现/popup到仅肖像VC的情况,反之亦然。 为了解决这个棘手的问题(苹果从未解决),你应该:
在iOS中<= 4和iOS> = 6:
UIViewController *vc = [[UIViewController alloc]init]; [self presentModalViewController:vc animated:NO]; [self dismissModalViewControllerAnimated:NO]; [vc release];
在iOS 5中:
UIWindow *window = [[UIApplication sharedApplication] keyWindow]; UIView *view = [window.subviews objectAtIndex:0]; [view removeFromSuperview]; [window addSubview:view];
这些将会强制UIKit重新评估您的所有应用程序,supportedInterfaceOrientations等
我有一个很好的方法混合https://stackoverflow.com/a/13982508/2516436和https://stackoverflow.com/a/17578272/2516436
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{ NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown; if(self.window.rootViewController){ UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController]; orientations = [presentedViewController supportedInterfaceOrientations]; } return orientations; } - (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController { if ([rootViewController isKindOfClass:[UITabBarController class]]) { UITabBarController* tabBarController = (UITabBarController*)rootViewController; return [self topViewControllerWithRootViewController:tabBarController.selectedViewController]; } else if ([rootViewController isKindOfClass:[UINavigationController class]]) { UINavigationController* navigationController = (UINavigationController*)rootViewController; return [self topViewControllerWithRootViewController:navigationController.visibleViewController]; } else if (rootViewController.presentedViewController) { UIViewController* presentedViewController = rootViewController.presentedViewController; return [self topViewControllerWithRootViewController:presentedViewController]; } else { return rootViewController; } }
并返回你想要支持每个UIViewController的任何方向
- (NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait; }
我有一个相对复杂的通用应用程序,使用UISplitViewController和UISegmentedController,并有几个视图必须在使用presentViewController
景观presentViewController
。 使用上面提到的方法,我能够让iPhone 5和iPhone 6工作得可以接受,但由于某种原因,iPad只是拒绝呈现为风景。 最后,我发现了一个简单的解决scheme(经过几个小时的阅读和试验和错误),适用于设备和ios 5&6。
步骤1)在控制器上,指定所需的方向(或多或less,如上所述)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationLandscapeRight); } -(BOOL)shouldAutorotate { return YES; } -(NSUInteger)supportedInterfaceOrientations { NSInteger mask = UIInterfaceOrientationMaskLandscape; return mask; }
步骤2)创build一个简单的UINavigationController子类并实现以下方法
-(BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; }
步骤3)呈现您的viewController
vc = [[MyViewController alloc]init]; MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc]; [self myNavigationController animated:YES completion:nil];
希望这对某人有帮助。
在这里不要沉闷,但你会如此善良地分享你的子类? 谢谢。
编辑:嗯,我终于做到了,这个子类很简单。 我只需要将AppDelegate
的navigationController
声明为UINavigationControllerSubclass
而不是默认的UINavigationController
,然后使用以下方法修改您的子类:
- (BOOL)shouldAutorotate { return _shouldRotate; }
所以我可以通过调用viewDidLoad
来设置我想旋转的任何视图
_navController = (UINavigationController *)self.navigationController; [_navController setShouldRotate : YES / NO]
希望这个调整将帮助其他人,谢谢你的提示!
提示:利用
- (NSUInteger)supportedInterfaceOrientations
在你的视图控制器,所以你最终没有在横向有一个肖像所需的视图,反之亦然。
我没有自己testing,但文档指出,你现在可以重写这些方法: supportedInterfaceOrientations
和preferredInterfaceOrientationForPresentation
。
你可能可以实现你想要的只是设置你想要的方向。
使用子类或类别的答案允许UINavigationController和UITabBarController类中的VC正常工作。 从横向标签栏控制器启动仅肖像模式失败。 如果你需要这样做,那么使用显示和隐藏非animation模式视图的技巧,但在viewDidAppear方法中 。 它在viewDidLoad或viewWillAppear中并不适用于我。
除此之外,上述解决scheme正常工作。
对于Monotouch,你可以这样做:
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations() { return UIInterfaceOrientationMask.LandscapeRight; } public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation() { return UIInterfaceOrientation.LandscapeRight; }
我看到很多答案,但没有得到有关方向的特定想法和答案,但看到链接很好理解的方向,并删除强制旋转ios6。
http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/
我认为这是充分的帮助。
只需进入project.plist,然后添加支持的界面方向,然后只添加肖像(底部主页button)和肖像(顶部主页button)。
您可以根据您的项目要求添加或删除那里的方向。
谢谢
1)检查你的项目设置和info.plist,并确保只有你想要的方向被选中。
2)将以下方法添加到最顶层的视图控制器(导航控制器/ tabbar控制器)
- (NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
3)将以下方法添加到您的应用程序委托
- (NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { return UIInterfaceOrientationMaskPortrait; }
把它放在你不想旋转的每个ViewController
的.m文件中:
- (NSUInteger)supportedInterfaceOrientations { //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft; return UIInterfaceOrientationMaskPortrait; }
在这里看到更多的信息。