如何在纵向应用程序中以纵向或横向呈现视图控制器

时间:2014-11-10 19:25:05

标签: ios uinavigationcontroller ios8 device-orientation

我有一个iPhone应用程序,其中大多数只是纵向的,但有一个视图控制器(视频播放器屏幕)必须支持纵向和横向(这仅适用于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];

也是纵向的,但是当设备转动时它会旋转到横向 - 到目前为止都很好。

问题在于,如果我将设备转为横向,视频播放器也会出现风景,但是当我通过后退按钮关闭视频播放器屏幕时,底层视图控制器(应该是仅限肖像) )现在也在景观中。如果我将设备旋转回纵向,则视图控制器也会旋转回纵向,然后从该点开始正确锁定设备。

当弹出上方的横向视图控制器时,如何让原始视图控制器(应该是仅限肖像)自动返回到肖像?

这个问题已被问过一百万次,但似乎已发布的修补程序都是在iOS 8中无效的黑客攻击。

更新:我找到了一个适用于iOS 8的“排序”修复程序。在我的UINavigationController子类中,我处理<UINavigationControllerDelegate>协议。我实现了这个方法:

- (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处于我希望它处于的状态。问题是当顶层视图控制器被解除并在屏幕外动画时,底层视图控制器仍处于格局中;然后它突然跳到肖像。不理想,但总比没有好。

更新2:我应该补充说我正在推送第二个视图控制器:

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

更新3:好的,这是完全可行的,适用于iOS 6及更高版本。修复甚至有点意义,虽然它的工作原因似乎不在任何地方的文档中。基本上,在视图控制器中,当设备仍处于横向状态时,当顶层视图控制器被关闭时,您需要将其重置为纵向,您只需添加以下内容:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

虽然我的UINavigationController的子类完全负责轮换调用,但断点显示在基础视图控制器上调用supportedInterfaceOrientations 之前顶层被解除,在顶层被解雇后,在导航控制器上调用它。所以我推断这个对视图控制器本身的调用是由iOS制作的,以确定底层视图控制器应该处于什么方向(并且它不会向导航控制器询问这个);如果它没有被明确覆盖,它将返回全部但倒置的参数,因此iOS只是将它放在原处。

5 个答案:

答案 0 :(得分:5)

事实证明这是一个简单的修复:你可以通过UINavigationController的子类驱动整个过程,就像我在这里发布的那样(即在视图控制器本身中没有实现任何这些旋转方法),除了任何查看控制器需要只有肖像,你还需要实现这个:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

使用断点,您可以看到在上面的推送视图控制器被解除之前调用此方法; iOS可能会使用此调用来确定&#34;显示的方向&#34;视图控制器应该在(对顶级视图控制器被解除后,对导航控制器子类的同一调用称为)。

在视图控制器中实现此方法,一切都按预期工作。

答案 1 :(得分:3)

在呈现特定的UIViewController子类时是纵向除外。这篇文章有很多帮助:~~因垃圾邮件而被删除~~

将Info.plist设置为支持,纵向,横向左侧,右侧风景

实现应用程序:supportedInterfaceOrientationsForWindow:像这样:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}
// (I specifically want landscape left for the movie viewing)

子类UINavigationController(windows的rootViewController)并覆盖如下:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait; // enforces the “portrait everything” requirement
}

最后,我必须确保自定义播放器视图控制器将“覆盖”支持的方向:

- (BOOL)shouldAutorotate
{
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationLandscapeLeft;
}

结果: UIViewController子类提供但在解除自定义视图控制器时,呈现视图控制器是肖像。

来自fantageek的文章:“系统将视图控制器支持的方向与应用程序支持的方向相交(由Info.plist文件或应用程序代理的应用程序确定:supportedInterfaceOrientationsForWindow:方法)以确定是否旋转。”

答案 2 :(得分:0)

我认为您应该更改为此并再试一次

-(NSUInteger)supportedInterfaceOrientations {
 if ([self.visibleViewController isKindOfClass:[MyVideoPlayerScreen class]]) 
 {
    return UIInterfaceOrientationMaskLandscape;
 } 
 else 
 {
    return UIInterfaceOrientationMaskPortrait;
 }
 }

答案 3 :(得分:0)

这是你怎么做的。

在呈现和呈现的控制器上实现这3种方法:

- (BOOL)shouldAutorotate {
    return NO; //-- for presented controller use YES
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape; //-- any orientation you need
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

现在您可以在演示控制器中使用:

[self presentViewController:presentedController animated:true completion:nil];

这样,当你回到呈现控制器时,它将具有正确的方向。

答案 4 :(得分:0)

我的案例有3个视图控制器:
- 第一视图控制器:肖像
- 第二视图控制器:横向右侧(具有导航控制器并由第一视图控制器呈现)
- 第三视图控制器:纵向(具有导航控制器并由第二视图控制器推动)
我的解决方案已经here了。希望这有帮助