导航控制器中的视图控制器方向更改

13

我有以下层次结构:

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

我想将RootViewController的方向锁定为Portrait,而让其他视图控制器保留所有方向。

如果我将以下代码放在子类化的UINavigationController中:

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

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

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

我的问题是,有没有一种方法只锁定RootViewController为纵向模式,但保留其他视图控制器的所有选项?

5个回答

28

点击这里查看在iOS 6中修复自动旋转和按视图基础设置方向支持的链接:http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

下面是您可以采取的步骤:

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

     - (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中,无论发生什么事件都要推送第二个视图控制器,请执行以下操作:

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

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

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

    对于iOS 5及以下版本,您可以设置

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

所有荣誉归功于约翰·迪萨尔沃,他在链接中编写了示例应用程序。

希望这能有所帮助。


1
这几乎是一个完整的解决方案,但在iOS 7和iOS 6上有一个问题。如果视图控制器仅支持纵向模式,并且在推送视图控制器之前设备处于横向模式,它将会以横向模式推送视图控制器!这只影响初始推送。旋转后,它会遵循视图控制器的设置。有什么好的解决方法吗? - PokerIncome.com
我正在尝试在Storyboard格式中使其工作。具体来说,是Appdelegate代码。有人在iOS 7.1中使用storyboards完成了这个吗? - Salx
你能看一下我的问题吗:https://stackoverflow.com/questions/45264386/child-view-controllers-orientation-change-in-uinavigationcontroller - nr5

2

在单例模式中

-(void)setOrientationSupport:(BOOL)flag{

    flag_orientationSupport_ = flag;
}

-(BOOL)getOrientationSupport{

    return flag_orientationSupport_;
}

在AppDelegate中

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

    if ([singleton getOrientationSupport])
        return UIInterfaceOrientationMaskAll;
    else
        return UIInterfaceOrientationMaskPortrait;
}

在viewWillAppear中添加以下代码,针对您想要支持方向的视图控制器。
[singleton setOrientationSupport:YES];

如果您想禁用控制器的方向,请使用以下方法:

[singleton setOrientationSupport:NO];

我把应用程序的左侧方向支持留给了我需要的一个方向,并添加了代码。现在完美地工作了。 - sandeepani

0
为了将定义允许的方向的责任委托给 UINavigationController 的子视图,可以使用 nav 控制器的 visibleViewController 属性,使导航控制器“询问”其子视图支持的方向。以下代码应该可以工作(Swift):
1. 子类化的导航控制器:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {

    if let visibleView = self.visibleViewController {
        return visibleView.supportedInterfaceOrientations()
    } else {
        return UIInterfaceOrientationMask.All
    }
}

2. 导航控制器的子视图(根视图):
// 仅支持竖屏
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

0

将此代码放到您的导航控制器中:

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

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

现在,将以下内容添加到您的根视图控制器中:
- (BOOL)shouldAutorotate
{
    return NO;
}

搞定了!


-1

我已经搜索了几个小时的解决方案!

所以在实现必要的方法后,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(显示)连接了视图:

enter image description here

这很重要,你正在使用

presentViewController:animated:completion:

而不是

pushViewController:animated:

否则方向将无法再次确定。
我一直在尝试类似的事情。
[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

或者UIViewController中,方向应该改变的地方调用它,我还尝试在我的自定义UIStoryboardSegues中,在presentingViewControllerdismissViewController之前调用它:

[UIViewController attemptRotationToDeviceOrientation];

或者

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

但是它们中没有一个起作用。当然,最后一个示例不应该是一个选择,因为如果苹果更改其 API 的任何内容,这可能会导致您的应用程序内部出现问题。

我还尝试使用AppDelegate方法,并在查找实际visibleViewController的正确UIInterfaceOrientation后始终在此方法中确定方向,但有时切换方向时会崩溃。所以我仍然想知道为什么它如此复杂,似乎也没有任何文档正确地解释它。即使遵循这部分没有帮助我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接