50

在我的应用程序中,我有多个视图,一些视图需要同时支持纵向和横向,而其他视图只需要支持纵向。因此,在项目摘要中,我都选择了所有方向。

下面的代码用于在 iOS 6 之前禁用给定视图控制器上的横向模式:

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

由于 shouldAutorotateToInterfaceOrientation 在 iOS6 中已被弃用,我已将上述内容替换为:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMask.Portrait;
}

当视图出现时,这个方法被正确调用(我可以设置一个断点来确保这一点),但界面仍然旋转到横向模式,不管我只为纵向模式返回掩码。我究竟做错了什么?

似乎目前不可能构建每个视图具有不同方向要求的应用程序。它似乎只遵循项目摘要中指定的方向。

4

15 回答 15

70

如果您使用UINavigationController 作为根窗口控制器,它将是它的 shouldAutorotate&supportedInterfaceOrientations将被调用。

如果您使用的是UITabBarController等,则同上。

所以要做的事情是继承你的导航/标签栏控制器并覆盖它的shouldAutorotate&supportedInterfaceOrientations方法。

于 2012-09-21T10:07:04.537 回答
30

尝试在 AppDelegate.m 中更改此代码

//   self.window.rootViewController = self.navigationController;

    [window setRootViewController:navigationController];

这是完整的答案

在 iOS 6 中未调用 shouldAutorotateToInterfaceOrientation

XD

于 2012-09-20T06:54:40.620 回答
20

In my case I have UINavigationController and my view controller inside. I had to subclass UINavigationController and, in order to support only Portrait, add this method:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

So in the UINavigationController subclass I need to check which orientation is supported by the current topViewController.

- (NSUInteger)supportedInterfaceOrientations
{
    return [[self topViewController] supportedInterfaceOrientations];
}
于 2012-09-20T13:25:20.250 回答
15

我发现的一件事是,如果您有一个仍在使用的旧应用程序

[window addSubView:viewcontroller.view];  //This is bad in so may ways but I see it all the time...

您需要将其更新为:

[window setRootViewController:viewcontroller]; //since iOS 4

一旦你这样做了,方向应该再次开始工作。

于 2012-09-20T18:29:44.960 回答
14

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;
}
于 2012-12-21T00:30:06.540 回答
10

正如其他人所说,如果您使用的是 UINavigationController 并且想要自定义各种视图,则您需要继承 UINavigationController 并确保您拥有这两个组件:

@implementation CustomNavigationController

// -------------------------------------------------------------------------------
//  supportedInterfaceOrientations:
//  Overridden to return the supportedInterfaceOrientations of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations]; 
}

// -------------------------------------------------------------------------------
//  shouldAutorotate
//  Overridden to return the shouldAutorotate value of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  YES when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

然后在任何只有肖像的视图中,您将包括:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

在任何观点中,这都是颠倒的:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}
于 2013-05-14T06:30:45.290 回答
2

基本上正如上面所说的那样,但更详细:

  1. 创建一个新文件,它是 UINavigationController 的子类
  2. 转到您的故事板,然后单击导航控制器,将其类设置为您刚刚创建的类
  3. 在此类(.m 文件)中添加以下代码,使其保持纵向模式:

    (BOOL)shouldAutorotate
    {
      return NO;
    } 
    
    (NSUInteger)supportedInterfaceOrientations
    {
     return UIInterfaceOrientationMaskPortrait;
    }
    

这对我有用

于 2013-02-17T22:25:53.400 回答
1

我认为最好的方法是做一个类别而不是子类化UINavigationControllerUITabbarController

你的 UINavigationController+Rotation.h

#import <UIKit/UIKit.h>

@interface UINavigationController (Rotation)

@end

你的 UINavigationController+Rotation.m

#import "UINavigationController+Rotation.h"

@implementation UINavigationController (Rotation)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}


@end

试着让你的所有控制器都导入这个类别,这就像一个魅力。您甚至可以使控制器不旋转并推动另一个将旋转的控制器。

于 2012-10-30T16:22:37.423 回答
1

这段代码对我有用:

-(BOOL)shouldAutorotate {
     return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

iPhone/iPad App Orientation查看我自己的答案

于 2012-09-22T03:23:32.233 回答
0

如果您正在使用,则必须在 的子类中UINavigationController实现shouldAutorotateand 。supportedInterfaceOrientationsUINavigationController

这些可以分两步控制,如果shouldAutorotate返回YES则有效supportedInterfaceOrientations。这是一个非常好的组合。

在这个例子中,除了 CoverFlowView 和 PreviewView,我的主要视图是 Portrait。CoverFlowView转移到PreviewView,PreviewView要跟随CoverFlowCView的旋转。

@implementation MyNavigationController

-(BOOL)shouldAutorotate
{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"PreviewView")])

return NO;

else

return YES;

}



-(NSUInteger)supportedInterfaceOrientations

{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"CoverFlowView")])

return UIInterfaceOrientationMaskAllButUpsideDown;

else

return UIInterfaceOrientationMaskPortrait;

}

...

@end
于 2012-09-24T15:58:13.413 回答
0

这里的答案为我指明了正确的方向,尽管我无法通过剪切和粘贴来使其工作,因为我在 UITabBarController 中使用 UINavigationControllers。所以我在 AppDelegate.m 中的版本看起来像这样,它将适用于 UITabBarController 中的 UITabBarControllers、UINavigationControllers 或 UINavigationControllers。如果您正在使用其他自定义容器控制器,则需要在此处添加它们(这有点令人讨厌)。

- (UIViewController*)terminalViewController:(UIViewController*)viewController
{
  if ([viewController isKindOfClass:[UITabBarController class]])
  {
    viewController = [(UITabBarController*)viewController selectedViewController];
    viewController = [self terminalViewController:viewController];
  }
  else if ([viewController isKindOfClass:[UINavigationController class]])
  {
    viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
  }

  return viewController;
}

- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
  NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
  UIViewController* viewController = [self terminalViewController:window.rootViewController];

  if (viewController)
    orientations = [viewController supportedInterfaceOrientations];

  return orientations;
}

另一个需要注意的关键是,您必须在 UIViewController 子类中覆盖supportedInterfaceOrientations,否则它将默认为您在Info.plist 中指定的内容。

于 2013-02-02T03:36:36.393 回答
0

我的解决方案:子类化UINavigationController并将其设置为window.rootViewController

层次结构的顶部视图控制器将控制方向,一些代码示例:子类 UINavigationController

于 2012-10-01T01:56:10.387 回答
0

我的情况和你一样。我知道你已经接受了一个答案,但我想我还是会再添加一个。这就是我理解新版本轮换系统工作的方式。根视图控制器是唯一被调用的视图控制器。我相信,原因在于,对于子视图控制器,经常旋转它们的视图是没有意义的,因为它们无论如何都会停留在根视图控制器的框架内。

那么,会发生什么。首先shouldAutorotate在根视图控制器上调用。如果NO返回,那么一切都会停止。如果YES返回则supportedInterfaceOrientations调用该方法。如果在此方法中确认了界面方向以及来自 Info.plist 或应用程序委托的全局支持的方向,则视图将旋转。在旋转之前shouldAutomaticallyForwardRotationMethods查询方法。如果YES(默认),那么所有的孩子都会像父母一样收到willanddidRotateTo...方法(他们反过来会将它转发给他们的孩子)。

我的解决方案(直到有一个更有说服力的解决方案)是在supportedInterfaceOrientations方法期间查询最后一个子视图控制器并返回其值。这让我可以旋转一些区域,同时只保留其他区域。我意识到它很脆弱,但我没有看到另一种不涉及使事件调用、回调等复杂化的方法。

于 2012-09-24T05:00:01.000 回答
0

尝试添加shouldAutorotate方法

于 2012-09-17T08:28:45.137 回答
0

首先,为了使您的应用程序在仅模式下工作,您应该返回UIInterfaceOrientationMaskLandscape. 如果您只想保留纵向模式,那么您做的事情是正确的。

只需UISupportedInterfaceOrientations在 Info.plist 中添加键并分配您的应用打算保留的界面方向值。

shouldAutoRotate此外,如果您想完全避免自动旋转,您应该返回 false 。但我建议你从这里返回 true 并在supportedInterfaceOrientations方法中指定正确的方向。

于 2012-09-17T09:26:31.727 回答