簡體   English   中英

如何在縱向應用程序中以縱向或橫向呈現視圖控制器

[英]How to present a view controller in portrait or landscape, in application that is portrait-only

我有一個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只是將它留在原處。

事實證明這是一個簡單的修復:你可以通過UINavigationController的子類驅動整個過程,就像我在這里發布的那樣(即在視圖控制器本身中沒有實現任何這些旋轉方法),除了對於任何需要是肖像的視圖控制器 - 你只需要實現這個:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

使用斷點,您可以看到在上面的推送視圖控制器被解除之前調用此方法; iOS可能會使用此調用來確定“顯示的”視圖控制器應該處於什么方向(在頂級視圖控制器被關閉調用導航控制器子類的相同調用)。

通過在視圖控制器中實現此方法,一切都按預期工作。

在呈現特定的UIViewController子類時,請使用EXCEPT。 這篇文章幫了很多忙:~~因為垃圾郵件被刪除了~~

將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子類呈現但在解除自定義視圖控制器時,呈現視圖控制器為Portrait。

來自fantageek的文章:“系統將視圖控制器支持的方向與應用程序支持的方向相交(由Info.plist文件或應用程序委托的應用程序確定:supportedInterfaceOrientationsForWindow:方法)以確定是否旋轉。”

我想你應該改變這一點再試一次

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

這是你如何做到的。

在呈現和呈現的控制器上實現這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];

這樣,當您返回呈現控制器時,它將具有正確的方向。

我的案例有3個視圖控制器:
- 第一個視圖控制器:肖像
- 第二視圖控制器:橫向右側(具有導航控制器並由第一視圖控制器呈現)
- 第三視圖控制器:縱向(具有導航控制器並被第二視圖控制器推動)
我的解決方案已經在這里 希望這可以幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM