![](/img/trans.png)
[英]Status bar hiding when landscape-only view controller is presented over portrait-only view controller
[英]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.