ios - 如何在仅纵向的应用程序中以纵向或横向呈现 View Controller

标签 ios uinavigationcontroller ios8 device-orientation

我有一个 iPhone 应用程序,其中大部分是纵向的,但有一个 View Controller (视频播放器屏幕)必须同时支持纵向和横向(这仅适用于 iOS 8)。为此,我将应用程序的 plist 设置为支持纵向和两种横向,然后子类化 UINavigationController ;在这个子类中我重写了

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {

    if ([self.visibleViewController isKindOfClass:[MyVideoPlayerScreen class]]) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }

}

大部分按预期工作:初始屏幕都是纵向屏幕,即使设备转到横向屏幕也保持纵向屏幕。视频播放器,最初呈现时:

MyVideoPlayerScreen *newVC = [MyVideoPlayerScreen new];
[self.navigationController pushViewController:newVC animated:YES];

也是纵向的,但是当设备转动时会旋转到横向 - 到目前为止一切正常。

问题是,如果我将设备转到横向,视频播放器也会横向,但是当我通过后退按钮关闭视频播放器屏幕时,底层 View Controller (应该是纵向的) ) 现在也在景观中。如果我将设备旋转回纵向, View Controller 也会旋转回纵向,然后从那时起它被正确锁定为仅纵向。

当弹出其上方的横向 View Controller 时,如何让原始 View Controller (应该是纵向的)自动返回纵向?

这个问题已经被问了一百万次,但似乎为它发布的修复都是在 iOS 8 中不再起作用的 hack。

更新:我找到了一个在 iOS 8 中有效的“某种”修复。在我的 UINavigationController 中。子类,我处理 <UINavigationControllerDelegate>协议(protocol)。我实现了这个方法:

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    if (![viewController isKindOfClass:[MyVideoPlayerScreen class]]) {

        // if the current orientation is not already portrait, we need this hack in order to set the root back to portrait
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (orientation != UIInterfaceOrientationPortrait) {

            // HACK: setting the root view controller to nil and back again "resets" the navigation bar to the correct orientation
            UIWindow *window = [[UIApplication sharedApplication] keyWindow];
            UIViewController *vc = window.rootViewController;
            window.rootViewController = nil;
            window.rootViewController = vc;

        }

    }

}

这至少让 UI 处于我想要的状态。问题是当顶层 View Controller 被关闭并在屏幕外动画时,底层 View Controller 仍然处于横向状态;然后它突然跳到肖像。不理想,但聊胜于无。

更新 2: 我应该补充说我正在插入第二个 View Controller :

ViewControllerPortraitLandscape *newVC = [ViewControllerPortraitLandscape new];
[self.navigationController pushViewController:newVC animated:YES];

更新 3: 好的,这完全可行,适用于 iOS 6 及更高版本。修复甚至有点意义,尽管它工作的原因似乎没有出现在任何地方的文档中。基本上,在 View Controller 中,当顶级 View Controller 被关闭而设备仍处于横向时,您需要将其重置为纵向,您只需要添加以下内容:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

虽然我的子类UINavigationController完全负责轮换调用,断点显示supportedInterfaceOrientations在顶层被关闭之前在底层 View Controller 上调用,在顶层被关闭之后在导航 Controller 上被调用。所以我推断这个对 View Controller 本身的调用是由 iOS 进行的,以确定底层 View Controller 应该处于什么方向(并且它不会为此询问导航 Controller );如果它没有被显式覆盖,它将返回 all-but-upside-down 参数,因此 iOS 只是将它保留在原处,横向。

最佳答案

原来这是一个简单的修复:你可以通过我在此处发布的 UINavigationController 的子类来驱动整个过程(即不在 View Controller 本身中实现任何这些旋转方法),除了对于任何需要纵向的 View Controller ,您还需要实现:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

有了断点,你可以看到这个方法是在它上面的推送 View Controller 被关闭之前调用的; iOS 大概使用此调用来确定“显示的” View Controller 应该处于什么方向(对导航 Controller 子类的相同调用在顶级 View Controller 被关闭后 被调用)。

通过在 View Controller 中实现此方法,一切都按预期进行。

关于ios - 如何在仅纵向的应用程序中以纵向或横向呈现 View Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26851387/

相关文章:

ios - 以编程方式创建导航 Controller 时黑屏

ios - 如何返回导航堆栈?

ios8 - 就 traitCollection 和大小类而言,横向是左还是右?

ios - 使用 shouldChangeCharactersInRange 限制输入的字符,但无法检测返回

ios - NativeScript ListView 滚动事件

ios - 调用 [self.navigationController pushViewController :animated:] 时需要很长时间将 UIView 推送到 UINavigation Controller

ios8 - GKMatchRequest 什么时候会是 'invalid' ?

swift - fatal error : unexpectedly found nil while unwrapping an Optional value swift

objective-c - UIImageView 的 UIImage 为零

ios - 如何在屏幕上绘图并将其转换为字符?