【问题标题】:How to force a UIViewController to Portrait orientation in iOS 6如何在 iOS 6 中强制 UIViewController 为纵向
【发布时间】:2012-09-13 06:09:21
【问题描述】:

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

【问题讨论】:

    标签: ios xcode ios6 xamarin.ios


    【解决方案1】:

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

    @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
    

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

    【讨论】:

    • 我可以确认这是可行的。如果您愿意,也可以将“[self.viewControllers lastObject]”替换为“self.topViewController”。
    • 如果您使用的是 UITabBarController ,那么这个 UINavigationController 类别没有帮助。您应该改为在 UITabBarController 上创建类别...
    • 此解决方案的问题是,当您弹出处于横向的控制器并且您的新顶部控制器仅支持纵向(反之亦然)时,它不起作用,在这种情况下不会调用这些回调并且我还没有找到如何强制新的顶部控制器进入正确方向的方法。有什么想法吗?
    • 我继承了 UINavigationController 并将其设置为 window.rootController。我实现了所有 3 种方法,当您更改设备的旋转时效果很好,问题是当您弹出视图控制器时会调用这些方法(与旋转无关)
    • 如果我正在从横向视图控制器推送或弹出,那么这会强制 UIViewController 变为横向。但是,如果我旋转成纵向,那么它可以正常工作,并且永远不会变成横向。从横向推送或弹出时的唯一问题。请帮忙
    【解决方案2】:

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

    【讨论】:

    • 这是 iOS 6 的最佳解决方案
    • @Phil,它适用于 iOS 6。但在某些情况下,比如从横向转到纵向,它就不起作用了。知道为什么会这样吗?
    • 非常有用的解决方案。对我来说,最好的。
    • 在 iOS 7 beta 6 上工作。在我的情况下从横向到纵向时工作。
    • 我在 iOS 6 中,但这不起作用。它在“UIViewController *presentedViewController”行中断。
    【解决方案3】:

    此答案与 OP 帖子的 cmets 中提出的问题有关:

    要强制视图以给定方向显示,请在 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:^{
                }];
         }];
    }
    

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

    【讨论】:

    • 谢谢,等我有几分钟空闲时间试试看
    • @RohanAgarwal 它确实像宣传的那样工作,我在这里使用它。但是您还需要实现已接受答案的代码,否则将无法正常工作。
    • 有没有人想出如何使用正确的旋转动画同时进行这项工作?看到它在没有动画的情况下从纵向切换到横向有点不和谐。它可以工作,只是希望让它工作得更好一点。
    • @Craig Watkinson 它在情节提要中不起作用。如果 iam 使用 presentVirecontroller 则不推荐使用 presentModalViewController 和 dismissModalViewControllerAnimated ,那么它将无法工作。请帮助我
    • 对于 ios8 dismissViewControllerAnimated 只是崩溃。我发现调用 [NWSAppDelegate sharedInstance].window.rootViewController = nil; [NWSAppDelegate sharedInstance].window.rootViewController = previousRootController 很好用。
    【解决方案4】:

    所以我在仅显示纵向模式视图时遇到了同样的问题。通常,我会创建一个UINavigationController,将viewController 设置为rootViewController,然后将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);
    }
    

    【讨论】:

    • 不适用于我的。我将这段代码全局设置为所有方向
    • supportedInterfaceOrientations 应该返回 NSUInteger,而不是 BOOL。见developer.apple.com/library/ios/#featuredarticles/…
    • 它的工作,对我来说是tabbarcontroller,再次感谢您的回答
    • FWIW,我也不得不走这条路......没有其他工作。谢谢。
    【解决方案5】:

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

    【讨论】:

    • 太棒了!需要最大限度地位于该线程的顶部。因为这是解决问题最简单的方法
    • @Roshan Jalgaonkar 在 ios 6 中它对我不起作用我只需要带有向下主页按钮的肖像我如何设置此 UIOrientation....
    • @Karthik 您必须在应用程序的目标中启用支持的旋转才能使其正常工作。
    【解决方案6】:

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

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

    在 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 等。

    【讨论】:

    • 无论 iOS 版本如何,对我来说,这些崩溃中的第一个。说在礼物结束之前不应调用解雇。
    • @arsenius 你能发布一个关于你如何使用它的sn-p吗?只要不是动画,就不应该有你提到的问题
    • 我还将第二个 sn-p 放入 viewDidAppear 中,它对我在 iOS 6 上的情况没有任何帮助。问题在这里:stackoverflow.com/questions/15654339/…
    • 对不起,这里有最后一条评论。将 iOS 5 代码移动到 viewDidAppear 会创建某种带有以下输出的无限循环:-[UIApplication beginIgnoringInteractionEvents] 溢出。忽略。
    【解决方案7】:

    我有一个很好的方法混合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;
    }
    

    【讨论】:

      【解决方案8】:

      我有一个使用 UISplitViewController 和 UISegmentedController 的相对复杂的通用应用程序,并且有一些视图必须使用 presentViewController 在 Landscape 中呈现。使用上面建议的方法,我能够让 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;
      
      }
      

      步骤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];
      

      希望这对某人有帮助。

      【讨论】:

        【解决方案9】:

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

        edit:好吧,我终于做到了,子类非常简单。我只需将AppDelegate 中的navigationController 声明为UINavigationControllerSubclass 而不是默认的UINavigationController,然后修改您的子类:

        - (BOOL)shouldAutorotate {
            return _shouldRotate;
        }
        

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

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

        希望此调整也能对其他人有所帮助,感谢您的提示!

        提示:利用

        - (NSUInteger)supportedInterfaceOrientations
        

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

        【讨论】:

          【解决方案10】:

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

          您可能可以实现您想要的,只需在这些方法中设置您想要的方向。

          【讨论】:

            【解决方案11】:

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

            除此之外,上面的解决方案都可以正常工作。

            【讨论】:

              【解决方案12】:

              对于 Monotouch,您可以这样做:

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

              【讨论】:

                【解决方案13】:

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

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

                我认为这是完全的帮助。

                【讨论】:

                  【解决方案14】:

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

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

                  谢谢

                  【讨论】:

                  • 它是关于特定的视图控制器而不是整个应用程序。
                  【解决方案15】:

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

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

                  - (NSUInteger) supportedInterfaceOrientations
                  {
                      return UIInterfaceOrientationMaskPortrait;
                  
                  }
                  

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

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

                  【讨论】:

                    【解决方案16】:

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

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

                    更多信息请参见here

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2018-02-17
                      • 1970-01-01
                      • 2016-02-21
                      • 2020-10-24
                      • 1970-01-01
                      • 2013-05-05
                      • 2013-02-14
                      • 1970-01-01
                      相关资源
                      最近更新 更多