【问题标题】:How to implement UIViewController rotation in response to orientation changes?如何实现 UIViewController 旋转以响应方向变化?
【发布时间】:2011-02-19 18:20:41
【问题描述】:

我的应用程序有大约 10 个不同的 UIViewControllers,如果设备旋转,我想将其中一个切换到横向模式。 (其余的,我想保持纵向。)

为了在那个视图上实现旋转,我需要实现其控制器的“shouldAutorotate”方法并返回 YES。由于此视图是通过导航控制器访问的,因此我还需要创建 UINavigationController 的子类,该子类实现“shouldAutorotate”并返回 YES。

此解决方案有效,但效果很好。我发现我推送到 UINavigationController 子类的所有 UIViewController 都会响应旋转,即使我实现了“shouldAutorotate”并返回 NO。 (记住:我只希望一个特定的 UIViewController 响应旋转,而不是导航控制器堆栈中的每个。)

所以,我的问题是:我怎样才能最好地做到这一点?我能想到的所有解决方案似乎 1) 很麻烦,2) 更糟糕的是,似乎都行不通。

非常感谢。

【问题讨论】:

    标签: iphone uiviewcontroller screen-orientation


    【解决方案1】:

    当你实现 UINavigationController 时,这个类是你的父类,它控制所有将被推入堆栈的子视图控制器。因此,RootViewController 是唯一对自动旋转说“是”或“否”的控制器。即使您将 Yes 传递给子视图控制器中的自动旋转,它们也不算数!

    这是 UINavigationController 的本质。所以要改变它,你有两个选择:

    1- 手动操作,需要经过一些繁琐的代码。

    2- 更改您的设计,使其与 UINavigationController 更兼容。应该旋转的单个视图应该由承载 NavController 的视图 RootViewController(不是导航根视图控制器——它们的名称相同,但完全不同)调用。当设备旋转时,它会将 NavController 推送到视图或另一个。

    3- 另一种方法也可以,但不推荐,因为它违反了 MVC 的概念,即你的 NavController 可以监听通知。可以和应该旋转的特定子视图可以发出通知——例如rotateMe,一旦 NavController 听到它,它就会旋转。

    正如我所说,它会起作用,但它违反了 MVC 模型——这对 Apple 来说很好,但从编程的角度来看不推荐。

    如果您需要进一步解释其中任何一个,请告诉我。

    【讨论】:

      【解决方案2】:

      仅当 [[navController topViewController] isKindOfClass:[RotatingViewController class]] 时在导航控制器子类上返回 YES

      【讨论】:

        【解决方案3】:

        我通过拥有一个根视图控制器(这可能是一个 UITabBarController)并在它的 viewDidLoad 方法中订阅旋转事件来做到这一点:

        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didRotate:)
                                                              name:@"UIDeviceOrientationDidChangeNotification" 
                                                              object:nil];
        

        然后在 didRotate: 方法中,我查看旋转发生时哪个视图控制器可见,以及手机的方向:

        - (void) didRotate:(NSNotification *)notification { 
        UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
        
        /*
            DEVICE JUST ROTATED TO PORTRAIT MODE
        
         orientation == UIDeviceOrientationFaceUp ||
         orientation == UIDeviceOrientationFaceDown
        
         */
        if(orientation == UIDeviceOrientationPortrait) {
        
        
        
        
        
        /*
            DEVICE JUST ROTATED TO LANDSCAPE MODE
         */
        }else if(orientation == UIInterfaceOrientationLandscapeLeft ||
                orientation == UIInterfaceOrientationLandscapeRight) {
        
        
        
        
        
        
        }
        
        }
        

        在 didRotate: 中你可以查看哪个是可见的 viewController 并从那里做你想做的事情。

        当特定视图控制器可见并且手机旋转为横向时,我会在横向模式下呈现模态视图控制器。如果任何其他视图控制器可见,我将忽略该事件。

        我强制我的模态视图控制器在其 viewWillAppear 方法中以横向模式显示 - 如果他们需要,我可以给任何人此代码。

        希望这会有所帮助。

        戴夫

        【讨论】:

          【解决方案4】:

          我已经看到使用您正在执行的方式的示例,但无法使其正常工作。我从 Apples 示例中找到了更好的方法。基本上你实现了一个 presentModalViewController 并创建另一个视图。 UIKit 做了一个基本的旋转动画并在视图之间淡入淡出。您必须将旋转视图实现为委托类,以便它可以回调其调用类以将其关闭并更新方向。

          - (void)orientationChanged:(NSNotification *)notification
          {
              // We must add a delay here, otherwise we'll swap in the new view
              // too quickly and we'll get an animation glitch
              NSLog(@"orientationChanged");
              [self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0];
          }
          

          然后显示横屏:

          - (void)updateLandscapeView
          {
          PortraitView *portraitView = [[PortraitView alloc] init];
          portraitView.delegate = self;
          UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
          if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
          {
              [self presentModalViewController: portraitView animated:YES];
              isShowingLandscapeView = YES;
              }
          else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
          {
              [self dismissModalViewControllerAnimated:YES];
              isShowingLandscapeView = NO;
              }
          [portraitView release];
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-24
            相关资源
            最近更新 更多