1

我有一个导航控制器,它一次显示两个视图控制器。它们是分层的,最前面的控制器可以向下拖动以显示下面的控制器。我的应用程序委托已配置,因此该应用程序仅在显示背面视图时才允许界面方向,如下所示。

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if (self.revealNavigationController.isViewRevealed)
    {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }

    return UIInterfaceOrientationMaskPortrait;
}

自然,这会导致前视图控制器和后视图控制器在设备旋转时旋转,但我只对旋转后视图控制器感兴趣。有没有办法在最前面的视图控制器中完全禁用旋转?

4

3 回答 3

1

您需要使用 iOS5 中添加的视图控制器包含 API。基本上,您需要做的是在您不再希望它参与旋转事件时删除您的一个视图控制器,并在它再次准备好时将其添加回来。一个样本将是...

@implementation AXRotationDemoViewController

- (id)init
{
    if ((self = [super init]))
    {
        self.oneViewController = [[AXLoggingViewController alloc] init];
        self.oneViewController.interfaceOrientations = UIInterfaceOrientationMaskPortrait;

        self.twoViewController = [[AXLoggingViewController alloc] init];
        self.twoViewController.interfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown;
    }

    return self;
}

- (void)viewDidLoad
{
    [self.oneViewController willMoveToParentViewController:self];
    [self addChildViewController:self.oneViewController];
    [self.view addSubview:self.oneViewController.view];
    [self.oneViewController didMoveToParentViewController:self];

    [self.twoViewController willMoveToParentViewController:self];
    [self addChildViewController:self.twoViewController];
    [self.view addSubview:self.twoViewController.view];
    [self.twoViewController didMoveToParentViewController:self];

    self.oneViewController.view.backgroundColor = [UIColor redColor];
    self.twoViewController.view.backgroundColor = [UIColor greenColor];

    UIButton * showBackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [showBackButton setTitle:@"Toggle Back/Front" forState:UIControlStateNormal];
    [showBackButton addTarget:self action:@selector(_toggle:) forControlEvents:UIControlEventTouchUpInside];
    [showBackButton sizeToFit];
    showBackButton.center = self.view.center;
    [self.view addSubview:showBackButton];
}

- (void)_toggle:(id)sender
{
    if ([self.childViewControllers containsObject:self.oneViewController])
    {
        [self.oneViewController.view removeFromSuperview];
        [self.oneViewController removeFromParentViewController];
    }
    else
    {
        [self.oneViewController willMoveToParentViewController:self];
        [self addChildViewController:self.oneViewController];
        [self.view addSubview:self.oneViewController.view];
        [self.oneViewController didMoveToParentViewController:self];

        UIWindow * window = self.view.window;
        UIViewController * hack = window.rootViewController;
        window.rootViewController = nil;
        window.rootViewController = hack;
    }
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    CGRect halfScreenFrame = self.view.bounds;
    halfScreenFrame.size.height /= 2;

    self.oneViewController.view.frame = halfScreenFrame;
    self.twoViewController.view.frame = CGRectOffset(halfScreenFrame, 0, halfScreenFrame.size.height);
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([self.childViewControllers containsObject:self.oneViewController])
        return self.oneViewController.supportedInterfaceOrientations;

    return self.twoViewController.supportedInterfaceOrientations;
}

@end

但是您可能会注意到,没有官方方法可以真正告诉 iOS 您已更改 的值supportedInterfaceOrientations,因此您最好的选择是 a) 使用我上面示例中的 hack 来强制 iOS 重做所有事情或 b) 不要让用户关闭后视图,直到设备再次处于纵向状态。

如果这不能很好地解释事情,这是我放在一起的示例。

于 2013-04-30T23:28:04.890 回答
0

axiixc 建议的解决方案通常更好,因此根据您的问题,您应该查看他的答案但是,这并没有解决我的问题。我UINavigationController在其中插入了视图控制器的视图作为索引 0 处的子视图。这样,视图将位于后面。然后我把它做成了UINavigationBar可拖动的,这样当它向下拖动时,它会显示后面的视图。然后最前面的视图将随导航栏一起移动。正如 axiixc 所建议的那样,我没有设法让它与引入 iOS 5 的视图控制器包含 API 一起工作。

相反,我从导航控制器中删除了视图并将其直接添加到UIWindow应用程序启动时,我自己处理了该视图的旋转并禁用了所有其他视图的旋转(也就是说,我在导航控制器上禁用了它)。

这就是我添加视图的方式-application:didFinishLaunchingWithOptions:

self.revealViewController = [[RevealViewController alloc] init];
[self.window insertSubview:self.revealViewController.view atIndex:0];

然后,就在那之后,我注册了UIDeviceOrientationDidChangeNotification.

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

我的didRotate:样子是这样的:(这是受 StackOverflow 上另一个答案的启发,我现在无法再次找到,抱歉)

- (void)didRotate:(NSNotification *)notification
{
    // Only rotate if the view is revealed
    if (self.revealNavigationController.isViewRevealed)
    {
        UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
        [self updateForDeviceOrientation:orientation animated:YES];
    }
}

我打电话-updateForDeviceOrientation:animated:

- (void)updateForDeviceOrientation:(UIDeviceOrientation)orientation animated:(BOOL)animated
{
    CGFloat degrees = 0.0f;
    switch (orientation)
    {
        case UIDeviceOrientationLandscapeLeft:
            degrees = 90.0f;
            break;
        case UIDeviceOrientationLandscapeRight:
            degrees = -90.0f;
            break;
        case UIDeviceOrientationPortrait:
            degrees = 0.0f;
            break;
        default:
            break;
    }

    CGFloat duration = (animated) ? [UIApplication sharedApplication].statusBarOrientationAnimationDuration : 0.0f;

    __weak typeof(self) weakSelf = self;
    [UIView animateWithDuration:duration animations:^{
        // Rotate view
        weakSelf.revealViewController.view.transform = CGAffineTransformIdentity;
        weakSelf.revealViewController.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));

        // Resize view for rotation
        CGFloat width, height;
        if (UIDeviceOrientationIsLandscape(orientation))
        {
            width = MAX(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
            height = MIN(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
        }
        else
        {
            width = MIN(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
            height = MAX(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
        }

        CGSize newSize = CGSizeMake(width, height);

        CGRect viewBounds = weakSelf.revealViewController.view.bounds;
        viewBounds.size = newSize;
        weakSelf.revealViewController.view.bounds = viewBounds;

        CGRect viewFrame = weakSelf.revealViewController.view.frame;
        viewFrame.size = newSize;
        weakSelf.revealViewController.view.bounds = viewFrame;
    }];
}
于 2013-05-03T08:01:24.857 回答
0

是的,看看 UIViewController 中的-supportedInterfaceOrientations方法。您返回一个UIInterfaceOrientationMask位掩码,该位掩码指定您希望 UIViewController 子类支持的方向。

于 2013-04-30T20:13:29.063 回答