85

由于ShouldAutorotateToInterfaceOrientation在 iOS 6 中已弃用,我用它来强制特定视图仅显示纵向,在 iOS 6 中执行此操作的正确方法是什么?这仅适用于我的应用程序的一个区域,所有其他视图都可以旋转。

4

16 回答 16

117

如果您希望我们所有的导航控制器都尊重顶部视图控制器,您可以使用一个类别,这样您就不必经历并更改一堆类名。

@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

正如一些评论指出的那样,这是解决问题的快速方法。更好的解决方案是子类 UINavigationController 并将这些方法放在那里。子类也有助于支持 6 和 7。

于 2012-09-22T00:49:55.323 回答
63

Ray Wenderlich 团队在“iOS6 By Tutorials”中特别提到了 iOS6 的最佳方法 - http://www.raywenderlich.com/UINavigationController ,并且在大多数情况下比子类化更好。

我将 iOS6 与UINavigationController包含一组作为初始视图控制器的情节提要一起使用。

//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;
}
于 2012-12-21T00:12:26.207 回答
39

该答案与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:^{
            }];
     }];
}

有趣的是,在撰写本文时,现在解雇都必须是动画的。如果两者都不是,那么您将得到一个白屏。不知道为什么这使它起作用,但确实如此!视觉效果因动画而异。

于 2013-02-24T22:39:20.403 回答
36

所以我在只显示纵向模式视图时遇到了同样的问题。通常,我会创建一个UINavigationController,将 设置viewControllerrootViewController,然后将 显示UINavigationController为模态视图。但在 iOS 6 中,viewController现在将向 navigationController 询问其支持的界面方向(默认情况下,现在全部适用于 iPad,除了颠倒的 iPhone 之外的一切)。

解决方案:我必须UINavigationController继承并覆盖自动旋转方法。有点蹩脚。

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
于 2012-09-20T22:59:16.770 回答
15

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;
}
于 2012-10-10T07:05:49.473 回答
10

我不同意@aprato 的回答,因为 UIViewController 旋转方法是在类别本身中声明的,因此如果您在另一个类别中覆盖然后会导致未定义的行为。在 UINavigationController(或 UITabBarController)子类中覆盖它们更安全

此外,这不包括您从横向视图推送/呈现/弹出到仅纵向 VC 或反之亦然的场景。要解决这个棘手的问题(Apple 从未解决过),您应该:

在 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 重新评估你所有的 shouldAutorotate 、supportedInterfaceOrientations 等。

于 2013-01-21T19:34:47.227 回答
3

我有一个很好的方法混合https://stackoverflow.com/a/13982508/2516436https://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;
}
于 2013-09-05T12:33:38.003 回答
1

不要在这里沉闷,但你会这么好心分享你的子类吗?谢谢你。

编辑:好吧,我终于做到了,子类做起来很简单。我只需要navigationControllerAppDelegateasUINavigationControllerSubclass而不是 default中声明UINavigationController,然后修改您的子类:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

所以我可以通过调用来设置我想要旋转的任何视图viewDidLoad

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

希望这个调整也能帮助其他人,谢谢你的提示!

提示:利用

- (NSUInteger)supportedInterfaceOrientations

在您的视图控制器中,因此您最终不会在横向中获得纵向所需的视图,反之亦然。

于 2012-09-20T23:59:27.267 回答
1

我有一个使用 UISplitViewController 和 UISegmentedController 的相对复杂的通用应用程序,并且有一些视图必须使用presentViewController. 使用上面建议的方法,我能够让 iPhone ios 5 和 6 正常工作,但出于某种原因,iPad 只是拒绝显示为横向。最后,我找到了一个适用于设备和 ios 5 和 6 的简单解决方案(经过数小时的阅读和反复试验后实施)。

步骤 1) 在控制器上,指定所需的方向(或多或少如上所述)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

Step 2) 创建一个简单的 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];

希望这对某人有帮助。

于 2013-02-09T12:49:18.200 回答
0

我自己没有对其进行测试,但文档指出您现在可以覆盖这些方法:supportedInterfaceOrientationspreferredInterfaceOrientationForPresentation.

您可能可以实现您想要的 y 在这些方法中仅设置您想要的方向。

于 2012-09-20T20:26:09.383 回答
0

使用子类或类别来允许 UINavigationController 和 UITabBarController 类中的 VC 的答案运行良好。从横向选项卡栏控制器启动仅纵向模式失败。如果您需要这样做,请使用显示和隐藏非动画模式视图的技巧,但在 viewDidAppear 方法中进行。它在 viewDidLoad 或 viewWillAppear 中对我不起作用。

除此之外,上述解决方案工作正常。

于 2013-06-14T11:38:39.767 回答
0

对于 Monotouch,您可以这样做:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}
于 2013-07-12T20:44:41.863 回答
0

我看到了很多答案,但没有得到关于方向的特定想法和答案,但看到链接很好地理解了方向并删除了 ios6 的强制旋转。

http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

我认为这是完全的帮助。

于 2013-09-13T06:30:09.433 回答
-1

只需转到 project.plist 然后添加支持的界面方向,然后仅添加 Portrait(底部主页按钮)和 Portrait(顶部主页按钮)。

您可以根据您的项目要求添加或删除那里的方向。

谢谢

于 2013-01-13T10:15:30.657 回答
-2

1) 检查您的项目设置和 info.plist 并确保只选择了您想要的方向。

2)将以下方法添加到最顶层的视图控制器(导航控制器/标签栏控制器)

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3)将以下方法添加到您的应用委托

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait;

}
于 2013-01-09T08:17:52.493 回答
-3

ViewController把它放在每个你不想旋转的 .m 文件中:

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

请参阅此处了解更多信息。

于 2013-06-23T21:22:26.297 回答