允许不同的导航控制器视图有不同的方向规则

Posted

技术标签:

【中文标题】允许不同的导航控制器视图有不同的方向规则【英文标题】:Allowing different navigation controller views to have different orientation rules 【发布时间】:2013-02-07 20:24:34 【问题描述】:

我正在尝试遵循上一个问题,以允许导航控制器视图控制器具有不同的方向规则。 Previous Question

例如,我有两个视图控制器,第一个是 Welcome,第二个是 Home。我希望第一个视图控制器只能是 Potrait,第二个(Home)允许端口/风景。

我不确定我是否完全了解如何完成此操作。完成后,我打算创建一个单独的项目来解释如何执行此操作,并将该问题添加到 Github/share 以供将来参考。

在这个特定的项目中,我使用的是侧视图控制器 github 项目。 PPRevealSideViewController。

我的应用委托如下:

// Then we setup the reveal side view controller with the root view controller as the navigation controller
welcomeViewController = [[MESWelcomeViewController alloc] init];
UINavigationController *navController = [[MESNavViewControllerSubClass alloc] initWithRootViewController:welcomeViewController];


self.revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:navController];
[self.revealSideViewController setDirectionsToShowBounce:PPRevealSideDirectionNone];
[self.revealSideViewController setPanInteractionsWhenClosed:PPRevealSideInteractionContentView | PPRevealSideInteractionNavigationBar];

//self.window.rootViewController = welcomeViewController;
self.window.rootViewController = self.revealSideViewController;
[self.window makeKeyAndVisible];

从上面你可以看到我已经将导航控制器子类化为 MESNavViewController。这是我对这个文件的看法:

@interface MESNavViewControllerSubClass : UINavigationController 
    BOOL setLandscapeOK;

MESNavViewController 的 Imp 文件:

-(void)viewDidLoad 
    NSLog(@"subclass called");


- (BOOL)shouldAutorotate

    return YES;


- (NSUInteger)supportedInterfaceOrientations

    if (self->setLandscapeOK) 
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    
    return UIInterfaceOrientationMaskPortrait;

在我的第一个(欢迎)视图控制器中,我有以下内容:

-(void)viewWillAppear 
    BOOL setLandscapeOK = NO;

- (NSInteger)supportedInterfaceOrientations 
    // Restriction for the welcome page to only allow potrait orientation
    return UIInterfaceOrientationMaskPortrait;

在我的第二个(主页)视图控制器中,我只有以下内容:

-(void)viewWillAppear 
    BOOL setLandscapeOK = YES;

我看到的是导航中的两个视图控制器都允许任何方向。我不确定我是否理解正确。希望我提供了足够的信息。

编辑 ----- 我已经更新了 PPRevealSidePanel 子类,它是最顶层的控制器。然后它持有导航控制器,而导航控制器又持有视图控制器。方向应由显示的视图控制器决定。

PPRevealSidePanel 子类 -

其次,我在实际视图控制器上尝试更新此子类的设置器 setLandscapeOK 时收到错误消息。 登录视图控制器 -

【问题讨论】:

你想完成什么?问题是什么? 这是在问题“例如,我有两个视图控制器,第一个是 Welcome,第二个 Home。我希望第一个视图控制器只是 Potrait,第二个(Home)允许端口/景观。” 【参考方案1】:

您能否查看以下讨论使用导航控制器处理方向的线程

NavController ShouldAutorotate

-anoop

【讨论】:

这是我尝试实现的,但不完全理解它应该如何工作。 好的,我已经为您做了一个示例,不确定这是否是您要寻找的......在示例中,View1 将自动旋转,而 View2 在同一个导航控制器下不会自动旋转找到代码在这里sendspace.com/file/b5jmjv 我已经下载了它,但在您的示例中,两个视图控制器都可以横向和纵向。我正在寻找一张固定的肖像和一张两者兼有的肖像? 好的,你还需要处理supportedInterfaceOrientations,preferredInterfaceOrientationForPresentation。我已经修改了代码,因为我家里没有 ios6 sdk,我无法测试它..但我认为这应该可以。可能会有小错误,但你应该能够调整。在新代码中,view1 将以纵向加载,因为我将首选方向设置为纵向,而 view2 将以任何方向加载,shouldrotate 代码保持不变。 sendspace.com/file/f2z81z 你是对的,我收到一个错误 - NSArray 没有可见的@interface 声明选择器 topViewController。由于我对您要解释的内容了解得不够多,说实话我迷失了……【参考方案2】:

是否调用了您的 viewWillAppear 方法?实际方法是- (void)viewWillAppear:(BOOL)animated

除此之外,问题是在 viewWillAppear 之前调用了 supportedInterfaceOrientations。尝试在 initWithNibName 方法中设置 BOOL 标志。

编辑:

类似这样的:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        self.setLandscapeOK = YES;
    
    return self;

编辑2:

我刚刚注意到您在 viewWillAppear 中将 setLandscapeOK 重新声明为一个新变量。这隐藏了该变量的超类实例。尝试使用 self.setLandscapeOK 而不是 BOOL setLandscapeOK

编辑 3:

由于您没有对主导航控制器进行子类化,因此上述内容将不起作用。您需要一种明确的方式来通知您的导航控制器它的子视图不希望它支持某些方向。当您推送仅纵向的视图控制器时,setLandscapeOK 应设置为 NO。

【讨论】:

我已更新方法无济于事。还添加了一个 NSLog 以确保它被调用......确实如此。我已经移动了 setLandscapeOK = NO; (对于第一个 Welcome 视图控制器)改为 ViewDidLoad 仍然没有区别。我无法进入 *withNibName,因为我没有使用 NIB 我将帖子更新为您可以尝试添加的内容。无论您是否使用 NIB,仍会调用该方法。 1.如果我设置了上面的 EDIT,我有一个错误 Property setLanscapeOKnot found... in MESWelcomeViewController。这是因为我将导航控制器子类化以添加此变量而不是视图控制器? 2. 在导航控制器子类中更新 self.setLandscapeOK 时也出现错误 - 在 MESNavViewControllerSubClass 上找不到属性 setLandscapeOK 您是要访问实例变量吗? 好的,我知道你现在在做什么。您的导航控制器是您的根视图控制器,并且您有两个单独的视图控制器,您可以将它们推送到导航控制器上。 iOS 根据占据整个屏幕的***别的根视图控制器处理旋转,在这种情况下,它是您的导航控制器。我会再次编辑我的帖子 不确定我是否理解这里的编辑或实际问题。我尝试将 PPRevealSidePanel 子类化,它也是***的,并从上面的问题信息中添加了先前在 Nav Controller 子类中的信息,但同样的问题仍然不起作用【参考方案3】:

在您的情况下出现的问题是您在该 UINavigationController 子类中覆盖了 -supportedInterfaceOrientations,因此该方法永远不会传递给它的子 ViewControllers。此外,您在 viewWillAppear 中声明了一个新的 setLandscapeOK BOOL,而不是更改全局。奇怪的是,根据您发布的代码,您的应用应该是纵向的,不允许所有方向,因为您似乎从未在 UINavigationController 子类中将 setLandscapeOK 布尔值设置为 YES。

但你似乎让事情变得比他们应该做的要复杂得多。你不应该需要那个 setLandscapeOK 布尔值,你不应该仅仅为了旋转问题而将 UINavigationController 或 PPRevealSideViewController 子类化。 PPRevealSideViewController 和 UINavigationController 都是容器 ViewControllers,也就是包含子 ViewControllers 的父 ViewControllers。默认情况下,当在父 ViewController 上调用方向回调时,它将调用并返回与子 ViewController 相同的方法。

当在 PPRevealSideViewController 上调用 -shouldAutoRotate、-supportedInterfaceOrientations 或 -shouldAutoRotateToInterfaceOrientation 时,它将在其 rootViewController 上调用相同的方法,在您的情况下是 UINavigationController。 UINavigationController 也是一个容器 ViewController 并将在当前可见的 ViewController 上调用相同的方法,在您的情况下是 WelcomeViewController 或 HomeViewController。

因此,您需要做的就是在 WelcomeViewController(仅返回纵向)和 HomeViewController(全部返回)中覆盖 -supportedInterfaceOrientations 和 -shouldAutoRotateToInterfaceOrientation。不要在 MESNavViewController 中覆盖这些方法,你甚至不需要这个子类。你不需要做任何其他事情。您也可以在所有 ViewController 中删除该 setLandscapeOK 布尔值。

【讨论】:

感谢您的回复。我已经更新了代码并删除了 Nav/revealside 的子类,注释掉了上述所有内容。我在 Home 和 Welcome 视图中都添加了 supportInterfaceOrientations,但 shouldAutoRorateToInterfaceOrientation 已被贬值……仅在两个视图控制器中都使用 supportInterfaceOrientations 是行不通的。他们现在总是允许端口/景观,还有其他想法吗? shouldAutoRorateToInterfaceOrientation 在 iOS6 中已被弃用,但如果您也支持 iOS5,您仍然需要实现它。如果您在 iOS5 上进行测试,请先尝试实现它。尝试在 supportedInterfaceOrientations 和 shouldAutorotateToInterfaceOrientation 方法中设置断点,并查看调用堆栈以了解何时以及由哪个父 ViewController 调用这些方法。 你是对的,但目前我正在为 iphone 6.0 构建。我在 Welcome/Home 控制器中实现了这两种方法,但都允许任何方向。我看过这里:-developer.apple.com/library/ios/#featuredarticles/… 这似乎设置正确,但它必须在某处覆盖。在 ios6.0 模拟器中进行测试时,我看到调用了 supportedInterfaceOrientations 但没有任何区别。 还有其他想法@Snppls?

以上是关于允许不同的导航控制器视图有不同的方向规则的主要内容,如果未能解决你的问题,请参考以下文章

1个单一导航控制器内的不同导航栏颜色?

在不同导航控制器中的视图之间切换

Swift - 在 UIPageViewController 中的 3 个不同视图控制器之间导航按钮

一个按钮,根据条件导航到不同的视图控制器

使用导航控制器将视图复制到项目 - “图像视图”的框架在运行时会有所不同

如何从不同的视图控制器更改导航栏图像