2009-06-09 63 views
24

我有一個UIViewController,在shouldAutorotateToInterfaceOrientation:中爲UIDeviceOrientationPortraitNO返回YES。在堆棧頂部顯示該視圖時,我使用pushViewController:animated:推送新的UIViewController。對於shouldAutorotateToInterfaceOrientation:中的任何內容,新控制器將返回YESUINavigationController和autorotation

第一個視圖拒絕旋轉(如預期的那樣)。一旦推入第二個視圖,用戶可以旋轉設備,UI將旋轉(也如預期的那樣)。如果第二個視圖處於橫向模式,並且用戶按下後退按鈕(調用popViewControllerAnimated:),則第一個視圖將出現旋轉(意外!)。

如果用戶將設備旋轉回縱向,視圖將旋轉,然後像以前一樣卡入縱向模式。這可以工作,但用戶直到他們旋轉後纔會變醜。所以我正在尋找一種方法讓這個視圖保持縱向模式。

迄今爲止我發現的唯一解決方法是使用-[UIDevice setOrientation:],它會引發警告(orientation是隻讀的),但由於它是實際定義的,所以會起作用。這是一個巨大的黑客攻擊,我想要一個真正的解決方案。爲了尋找真正的解決方案,我將GDB附加到Photos應用程序(MobileSlideshow.app)中,並發現它也使用-[UIDevice setOrientation:]。雖然我猜他們有不同的規則,但作爲內部應用程序。

是否有正確的方法來實現預期的自轉行爲?

+0

我相信有應用程序的例子(大概)在應用程序商店中使用setOrientation。一個是Tweetie,它可以在寫推文時強制風景鍵盤。也許他們逃避了它,因爲它不是默認設置。 – 2009-06-09 15:50:50

+0

現在是2014年,這個問題仍然發生在ios 8上。有沒有人找到真正的答案,但這個問題看起來不像黑客? – 2014-10-31 16:17:59

回答

1

我正要告訴你,可能沒有辦法,但後來我有了一個想法。如果你使用兩個單獨的UINavigationController s:一個控制根視圖並禁止旋轉,一個用於允許它的子視圖,你可能能夠使它工作。您將手動處理往來根控制器和子控制器的轉換。

你必須修補兒童導航控制器以擁有正確的後退按鈕。當然,你必須處理後退按鈕。您可能必須使用虛擬UINavigationBar才能從一個導航控制器執行動畫,以便轉換看起來正確。您還必須爲導航控制器之間的「推送」過渡設置動畫,這可能需要稍微調整以使其看起來正確。您將不得不:

  1. 配置一個虛擬導航欄,使其與導航控制器完全匹配,並將其直接放置在導航控制器欄的頂部。在右邊緣
  2. (您可以複製當前視圖控制器的UINavigationItem的配置,並推動它)
  3. 將新的導航控制器關閉屏幕從右到左的動畫新老控制器的幀的運動
  4. 用於輸入視圖控制器創建UINavigationItem的副本,並推動它虛設導航欄
  5. 當在動畫完成上,從視圖中去除僞UINavigationBar,並且還傳出導航控制器。

所有這些都是很多工作,但是如果你非常聰明(而且非常堅韌),那麼你可能會得到它的工作。我很想看到結果!

這就是說,你可能會更好只使用setOrientation:,並採取與App Store的審批流程;-)

1

與3.0 OS再試一次(現在我們可以談論它),你的機會。這兩種特殊情況已經在3.0摸索出:

  1. 呈現肖像模式的看法在橫向視圖,反之亦然。一個例子是郵件中用於查看附件的3.0版之前的行爲。您可以旋轉以橫向查看PDF並在取消附件視圖時恢復消息的縱向視圖。 (現在我們在3.0中已經有了橫向消息視圖,這種行爲似乎已經消失了)。

  2. 混合視圖堆棧中的方向並在彈出堆棧時返回正確的方向。一個例子是電影的桌面視圖和YouTube應用中的電影視圖之間的轉換。

似乎有一些棘手的審美問題,如何默認過渡所有的排列應該看起來。如果你用慢鏡頭查看,有一些奇怪的元素,但它會在你自己的代碼中向後彎曲。

+0

我試過這個,#1似乎工作正常,但#2不適合我。我使用表格視圖控制器設置了一個導航控制器項目。根視圖不能旋轉,但推送的視圖可以。當你彈出第二個視圖時,它將保持旋轉狀態。實際上,導航欄項目似乎很困惑,甚至在彈出它後顯示第二個視圖的標題。 – 2010-02-01 04:36:32

0

所以這個惱人的錯誤是一個很難很長的路要走,從iOS的1到iOS 4

我相信我們有它複製this bug,讓蘋果知道我們真的希望它固定的最佳解決方案。我剛剛在bug ID 8478525下再次報告了它。

5

這是一篇舊帖子,但是因爲它尚未解決。我想分享我的解決方案,對於任何其他可能頭痛的人。

目標: UINavigationController和堆棧中的大多數viewcontrollers固定在縱向,除了堆棧中的一個viewcontroller被允許旋轉到縱向和橫向。

問題: 直觀地,我通過檢查topViewController是否爲rotableViewController來設置選擇性的shouldAutorotateToInterfaceOrientation。但是,在風景模式下從rotableViewController回彈後,導航控制器現在以橫向模式顯示,儘管不允許。

解決方案:殺手將禁止旋轉viewWillAppear,並且當前&關閉一個沒有動畫的modalViewController。

  1. appViewController作爲主機 viewController添加到窗口中,即,Rooter比RootViewController;
  2. 將navigationController添加到appViewController,並將 委託設置爲appViewController;
  3. 在AppViewController


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    if (interfaceOrientation == UIInterfaceOrientationPortrait) return YES; 
    return canRotate; 
} 


- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    [viewController viewDidAppear:animated]; 
    canRotate = ([navigationController.topViewController isKindOfClass:[MyRotatable class]]); 
} 


- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    [viewController viewWillAppear:animated]; 
    if (![navigationController.topViewController isKindOfClass:[MyRotatable class]]) { 
     canRotate = NO; 
     UIViewController * blanck = [[UIViewController alloc] initWithNibName:nil bundle:nil]; 
     [self presentModalViewController:blanck animated:NO]; 
     [self dismissModalViewControllerAnimated:NO]; 
     [blanck release]; 
    } 
} 
6

到的UIDevice setOrientation的法律替代如下:

UIWindow* window = UIApplication.sharedApplication.keyWindow; 
UIView* view = [window.subviews objectAtIndex:0]; 
[view removeFromSuperview]; 
[window addSubview:view]; 

強制當前視圖控制器,以評估其方向,調用shouldAutorotateToInterfaceOrientation和任何違禁方向切換了。

E.g.下面的代碼將在支持所有方向,但其母公司視圖控制器只能用於支持橫向:

- (void)popBack 
{ 
    [self.navigationController popToRootViewControllerAnimated:YES]; 
} 

- (IBAction)backPressed:(id)sender 
{ 
    portraitOrientationPermitted = NO; 

    // Force the framework to re-evaluate the interface orientation. 
    UIWindow* window = UIApplication.sharedApplication.keyWindow; 
    UIView* view = [window.subviews objectAtIndex:0]; 
    [view removeFromSuperview]; 
    [window addSubview:view]; 

    [self performSelector:@selector(popBack) withObject:nil afterDelay:0.8]; 

    portraitOrientationPermitted = YES; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return portraitOrientationPermitted || 
     UIInterfaceOrientationIsLandscape(interfaceOrientation); 
} 
+0

骯髒的骯髒的黑客,但它的作品。 – beefon 2012-01-10 04:40:15

+2

在iOS 7上不適用於我。但是,刪除窗口的rootViewController並將其放回原處。只要把它放在那裏,以防有人遇到同樣的問題。 – entropy 2013-09-16 08:05:51

1

我發現這個問題一個很好的解決方法。線索是支持所有方位爲所有UINavigationController的意見。

我在控制器中有2個視圖。根視圖僅支持LandscapeRight,第二種支持支持LandscapeRightPortrait

第二視圖shouldAutorotateToInterfaceOrientation方法看起來像往常一樣:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight) || 
      (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

解決方法本身包含在根視圖源 現在根視圖中的代碼方面旋轉,但用戶無法看到它。

//auxiliary function 
-(void) fixOrientation:(UIInterfaceOrientation)orientation 
{ 
    if (orientation == UIInterfaceOrientationPortrait) 
     self.view.transform = CGAffineTransformMakeRotation(M_PI_2); 
    else if (orientation == UIInterfaceOrientationLandscapeRight) 
     self.view.transform = CGAffineTransformMakeRotation(0); 
} 

-(void) viewWillAppear:(BOOL)animated 
{ 
    [self fixOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    [self fixOrientation:interfaceOrientation]; 
    //notice, that both orientations are accepted 
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight) || 
      (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

//these two functions helps to avoid blinking 
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    [UIView setAnimationsEnabled:NO]; // disable animations temporarily 

} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{ 
    [UIView setAnimationsEnabled:YES]; // rotation finished, re-enable them 
} 
4

iOS 5增加了+ [UIViewController attemptRotationToDeviceOrientation],它爲我解決了這個問題。

+1

根據文檔(「嘗試將所有窗口旋轉到設備的方向」),似乎這是針對反向用例的,即您推送一個新的視圖控制器,支持前一個不支持的界面方向。 – Koraktor 2013-01-04 18:40:47

相關問題