【问题标题】:ViewController in UINavigationController orientation changeUINavigationController 中的 ViewController 方向更改
【发布时间】:2013-01-02 08:50:53
【问题描述】:

所以我有以下层次结构:

UINavigationController --> RootViewController (UIViewController) --> UITableViewController --> DetailViewController (UIViewController)

我想将 RootViewController 上的方向锁定为仅纵向,但将所有方向留给其余视图控制器。

如果我把它放到子类UINavigationController:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

然后所有视图控制器都被锁定为纵向。

我的问题是,有没有办法只将 RootViewController 锁定为 Portrait,而将所有选项留给其他视图控制器?

【问题讨论】:

    标签: iphone ios ipad uinavigationcontroller orientation


    【解决方案1】:

    要将定义允许方向的责任委托给 UINavigationController 的子视图,可以使用导航控制器的 visibleViewController 属性使导航控制器“询问”其支持的方向的子视图。以下代码应该可以工作(Swift):

    1. 子类导航控制器:

      override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
      
          if let visibleView = self.visibleViewController {
              return visibleView.supportedInterfaceOrientations()
          } else {
              return UIInterfaceOrientationMask.All
          }
      }
      
    2. 导航控制器的子视图(根视图):

      // Restrict to portrait
      override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
          return UIInterfaceOrientationMask.Portrait
      }
      

    【讨论】:

      【解决方案2】:

      我已经寻找解决方案几个小时了!

      所以在到处实现所需的方法之后。 shouldAutorotate 不需要设置为YES,因为它已经设置为默认值:

      - (NSUInteger)supportedInterfaceOrientations{
          return UIInterfaceOrientationMaskPortrait;
      }
      
      - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
           return UIInterfaceOrientationPortrait;
      }
      

      当需要显示需要与其他视图不同的方向的UIViewController 时,我创建了一个UIStoryboardSegue,其中包含此实现:

      #import "Showing.h"
      
      @implementation Showing
      
      - (void)perform{
          NSLog(@"Showing");
          UIViewController *sourceVC = self.sourceViewController;
          UIViewController *presentingVC = self.destinationViewController;
      
          [sourceVC.navigationController presentViewController:presentingVC 
                                                      animated:YES 
                                                    completion:nil];
      }
      
      @end
      

      UIStoryboard 中,我将视图与这个segue 连接起来(showing):

      这很重要,你正在使用

      presentViewController:animated:completion:
      

      与否

      pushViewController:animated:
      

      否则将无法再次确定方向。


      我一直在尝试像
      [UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
      

      这个在UIViewController 中的方向应该改变,我也尝试在presentingViewControllerdismissViewController 之前在我的自定义UIStoryboardSegues 中调用它:

      [UIViewController attemptRotationToDeviceOrientation];
      

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

      但是没有一个工作。当然最后一个例子不应该是一个选项,因为如果苹果会改变他们的任何 api 这可能会导致你的应用程序内部出现问题。

      我也尝试使用AppDelegate 方法,并在寻找实际visibleViewController 的正确UIInterfaceOrientation 后始终确定此方法内的方向,但有时在从一个方向切换到另一个方向时会发生崩溃。所以我仍然想知道为什么它变得如此复杂,而且似乎也没有任何文档可以正确解释它。 甚至关注this part didn't help我。

      【讨论】:

        【解决方案3】:

        单例

        -(void)setOrientationSupport:(BOOL)flag{
        
            flag_orientationSupport_ = flag;
        }
        
        -(BOOL)getOrientationSupport{
        
            return flag_orientationSupport_;
        }
        

        在应用程序中

        - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
        {
        
            if ([singleton getOrientationSupport])
                return UIInterfaceOrientationMaskAll;
            else
                return UIInterfaceOrientationMaskPortrait;
        }
        

        在viewwillappear中添加如下代码

        对于你想要支持方向的视图控制器

        [singleton setOrientationSupport:YES];
        

        到那些你想要禁用方向的控制器

        [singleton setOrientationSupport:NO];
        

        【讨论】:

        • 我将应用程序左方向支持保留为我需要的一个方向,并添加了代码。完美运行。
        【解决方案4】:

        查看此处的链接以修复 iOS 6 中的自动旋转并根据视图设置方向支持:http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

        你可以这样做:

        1. 在您的 .m 文件中创建一个自定义导航控制器,它是 UINavigationController 的子类:

           - (BOOL)shouldAutorotate
           {
                return self.topViewController.shouldAutorotate;
           }
           - (NSUInteger)supportedInterfaceOrientations
           {
                return self.topViewController.supportedInterfaceOrientations;
           }
          
        2. 在你的AppDelegate.h

            @interface AppDelegate : UIResponder <UIApplicationDelegate> {
          
                UINavigationController *navigationController;
                ViewController *viewController;
            }
          
            @property (strong, nonatomic) UIWindow *window;
            @property (strong, nonatomic) ViewController *viewController;
          

          AppDelegate.m

            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
            {
                  // set initial view
                 self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
          
                 viewController = [[ViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
          
                 navigationController = [[CustomNavigationController alloc]
                              initWithRootViewController:viewController]; // iOS 6 autorotation fix
                 [navigationController setNavigationBarHidden:YES animated:NO];
          
                  self.window = [[UIWindow alloc]
                     initWithFrame:[[UIScreen mainScreen] bounds]];
          
                  [self.window setRootViewController:navigationController]; // iOS 6 autorotation fix
                  //[self.window addSubview:navigationController.view];
          
                  [self.window makeKeyAndVisible];
          
          
                   return YES;
            }
          
          
            - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  // iOS 6 autorotation fix
            {
                    return UIInterfaceOrientationMaskAll;
          
            }
          
        3. 在您的 rootViewController 中,无论事件推送第二个视图控制器,请执行以下操作:

            - (IBAction)pushSecondViewController:(id)sender {
          
              // push second view controller
              SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
              [self.navigationController pushViewController:secondViewController animated:YES];
             }
          
        4. 在你的每个视图控制器中,添加

             - (BOOL)shouldAutorotate{}
             - (NSUInteger)supportedInterfaceOrientations{}
          

          对于 iOS 6,您可以单独设置每个视图控制器所需的方向支持。

          对于iOS 5及以下,可以设置

             - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{}
          

        所有功劳归于在链接中编写示例应用的 John DiSalvo。

        希望这会有所帮助。

        【讨论】:

        • 这几乎是一个完整的解决方案,在 iOS 7 和 iOS 6 上存在一个问题。如果视图控制器仅支持纵向,并且设备在推送视图控制器之前是横向的。它将以横向推动视图控制器!这只会影响初始推送。旋转后,它将遵循视图控制器的设置。知道如何解决它吗?
        • 我正在努力让它以故事板格式工作。具体来说,appdelegate 代码。有没有人在 iOS 7.1 中使用情节提要完成此操作?
        • 你能看看我的问题吗:stackoverflow.com/questions/45264386/…
        【解决方案5】:

        把它放在你的导航控制器中:

        - (BOOL)shouldAutorotate
        {
            return self.topViewController.shouldAutorotate;
        }
        
        -(NSUInteger)supportedInterfaceOrientations
        {
            return UIInterfaceOrientationMaskAll;
        }
        

        现在,将其添加到您的根视图控制器:

        - (BOOL)shouldAutorotate
        {
            return NO;
        }
        

        应该这样做!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-07
          • 1970-01-01
          • 2015-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多