iOS:禁用子视图的自动旋转

Jas*_*rge 18 orientation uiview ipad device-orientation ios

我有一个支持方向更改的iPad应用程序的嵌套视图层次结构.它看起来与以下类似.

UIViewController
    UIView
        - UIView
            - UIImageView (disable rotation)
            - UIImageView
            - UIView (disable rotation)
        - UIView
        - UIView
        ...
Run Code Online (Sandbox Code Playgroud)

我想锁定一些子视图的方向,同时允许其他人自动旋转和调整大小.我似乎无法弄清楚如何实现这一目标.

一种方法似乎是手动旋转子视图willAnimateRotationToInterfaceOrientation:.鉴于SDK正在执行我将要撤消的轮换,这并不是特别有吸引力.

有没有办法简单地禁用子视图的方向更改或其他方法来重构我的层次结构?

Stu*_*art 22

自动旋转由视图的UIViewController(shouldAutorotateToInterfaceOrientation:)处理,因此一种方法是排列层次结构,使得可旋转视图由一个视图控制器管理,而不可旋转视图由另一个视图控制器管理.然后,这两个UIViewController的根视图都需要添加到窗口/超级视图中.

这里的细微之处在于,如果在同一级别上有两个视图控制器的视图(即添加了通过addSubview:),则只有第一个视图控制器(通常是窗口的rootViewController)才会收到shouldAutorotateToInterfaceOrientation:消息.

我自己使用这种方法来实现旋转的工具栏,而主视图却没有.

Apple的技术问答QA1688("为什么我的UIViewController不会随设备一起旋转?")谈论这个问题.


iOS 6更新:

Autorotation现在使用UIViewController's' shouldAutorotatesupportedInterfaceOrientations方法.默认情况下shouldAutorotate返回YES,但请记住,除了视图之外的视图控制器rootViewController是窗口的直接子视图,无论如何都不会收到旋转回调.


iOS 6示例代码:

使用"单一视图应用程序"模板创建一个新项目,并确保选中"使用故事板".我们将使用提供的ViewController类作为旋转视图控制器(如果你愿意,可以重命名!),并创建一个UIViewController名为的第二个子类NonRotatingViewController.虽然此视图控制器永远不会收到旋转回调,但为了完整性和清晰度,请在以下代码中添加以下代码NonRotatingViewController.m:

- (BOOL)shouldAutorotate
{
    return NO;
}
Run Code Online (Sandbox Code Playgroud)

在该MainStoryboard文件中,拖出一个新的视图控制器对象并将其类设置为NonRotatingViewController,并将其Storyboard ID设置为"NonRotatingVC".当你在那里时,将旋转视图控制器视图的背景颜色更改为清除(非旋转视图将添加到此视图下方),并为每个视图添加标签.在AppDelegate.m,添加以下代码:

#import "NonRotatingViewController.h"

// ...
// ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    NonRotatingViewController *nonRotatingVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"NonRotatingVC"];
    [self.window addSubview:nonRotatingVC.view];
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

这只是实例化一个非旋转视图控制器并将其视图直接添加到窗口(此时NB rootViewController已经由故事板设置了窗口).

运行该项目.旋转设备并惊叹于一个标签旋转而另一个标签保持静止!


iOS 6之前的示例代码:

我在一个新项目中做到了这一点 - 一个新的基于视图的应用程序会做得很好.添加两个新的视图控制器:RotatingViewControllerNonRotatingViewController.在他们的每个笔尖里面,我只添加了一个标签来描述视图是否应该旋转.添加以下代码:

' RotatingViewController.m'

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}
Run Code Online (Sandbox Code Playgroud)


' NonRotatingViewController.m'

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if (interfaceOrientation == UIInterfaceOrientationPortrait) {    // Or whatever orientation it will be presented in.
        return YES;
    }
    return NO;
}
Run Code Online (Sandbox Code Playgroud)


' AppDelegate.m'

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    RotatingViewController *rotating = [[RotatingViewController alloc] initWithNibName:@"RotatingViewController" bundle:nil];
    self.rotatingViewController = rotating;
    [rotating release];

    NonRotatingViewController *nonRotating = [[NonRotatingViewController alloc] initWithNibName:@"NonRotatingViewController" bundle:nil];
    self.nonRotatingViewController = nonRotating;
    [nonRotating release];

    [self.window addSubview:self.rotatingViewController.view];
    [self.window insertSubview:self.nonRotatingViewController.view belowSubview:self.rotatingViewController.view];

    [self.window makeKeyAndVisible];

    return YES;
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.

  • @Stuart任何想法如何在iOS 8中运行? (2认同)

mah*_*udz 10

这是另一种方式.只需将此代码放入viewController viewDidLoad:

    YourAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
        // the view you don't want rotated (there could be a heierarchy of views here):
    UIView *nonRotatingView = [[UIView alloc] initWithFrame:CGRectMake(100,0,30,500)];
    nonRotatingView.backgroundColor = [UIColor purpleColor];

        // make sure self.view and its children are transparent so you can see through to this view that will not be rotated behind self.view.

    [delegate.window insertSubview:nonRotatingView  belowSubview:self.view];

        // you can't put it in the front using:
        //    [delegate.window insertSubview:nonRotatingView aboveSubview:self.view];
        // It will show up the same as before

    // you should declare nonRotatingView as a property so you can easily access it for removal, etc.
Run Code Online (Sandbox Code Playgroud)

  • nonRotatingView位于应用程序窗口和ViewControllers视图之间,不受viewcontroller管理.viewcontroller将仅处理其视图的方向更改,并将忽略它与窗口之间放置的视图. (2认同)