0

所以我有這樣的iPhone應用程序,像這樣的嵌套設置: [RootViewController] - > [UITabBarController] - > [UINavigationController] - > [subViewControllers]。一切都以編程方式構建,而不是在Interface Builder中構建。UINavigationController工具欄和設備方向(旋轉)

我只是想支持所有設備的方向。我所有的AutoResizing蒙版都已設置完畢,並且所有內容都會根據需要進行旋轉和展開/合同。除了NavigationController的navBar和工具欄以外的所有內容。 (通常,這些意見將自動取決於方向自動調整大小。即在景觀,導航欄和工具欄會自動調整到約32PX,並44px在Portrai模式。)有什麼奇特之處在於導航控制器的子視圖是在調整​​,但實際的navBar和工具欄不是。換句話說,無論在哪個方向上,內容都可以拉伸/縮小約12像素左右,就像導航欄和工具欄調整大小一樣。這似乎是自動調整的口罩在做他們的工作。

因此,爲了嘗試解決這種情況,我爲UINavigationController創建了一個響應'willRotateToInterfaceOrientation:duration:'的類別,以觸發'sizeToFit'選擇器。 (這種技術來自於堆棧溢出另一篇文章,有類似的問題。)我發現,在我的研究中,只有最外層的視圖控制器接收到該消息,但是,讓我有選項卡控制器,在我的根視圖控制器調用這裏面然後在導航控制器上調用它,等等。這就解決了這個問題,現在我的嵌套視圖控制器會在外部視圖旋轉時得到通知。使用sizeToFit技術,導航欄和工具欄都將自行調整大小。但是,這仍然會導致重新定位工具欄的問題,以彌補尺寸更改的偏移量。 (因爲我們在iPhone中的視圖座標從左上角開始)

在willRotate方法中做這個棘手的事情是我們無法知道新的邊界視圖維度是什麼,我們也不知道什麼是什麼我們目前的方向是。 (除非你開啓了deviceOrientationNotifications,我不這麼做。)我們所需要做的就是新的方向是什麼,以及我們工具欄的當前幀值是什麼。我可以硬編碼並使用一張草稿紙以舊式方式計算幀調整,但我真的想保留動態視圖大小調整功能,而不對設備的屏幕尺寸做任何假設。

因此,使用下面的代碼,我設法通過簡單地彌補這一由12像素相對於它只是成爲大小「碰撞」的工具欄。爲了防止用戶翻轉設備時發生過度碰撞,我使用當前工具欄的框架高度來導出當前的方向。 (這意味着我仍然想提出關於工具欄的前後尺寸的假設,但我覺得那更好,因爲我能影響,爲而不是試圖以編程方式調整設備的物理屏幕的學位。)

@implementation UINavigationController (BLUINavigationControllerAutoRotate) 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
{ 
    return TRUE; 
} 

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 

    // Resize the navBar 
    [[self navigationBar] performSelector:@selector(sizeToFit) 
           withObject:nil 
           afterDelay:(0.5f * duration)]; 

    // Read our current frame size 
    CGRect toolbarFrame = self.toolbar.frame; 

    // Prevent over adjusting when flipping the device 
    if ((toolbarFrame.size.height < 38 
     && (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft 
      || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)) 
     || (toolbarFrame.size.height > 38 
      && (toInterfaceOrientation == UIInterfaceOrientationPortrait 
       || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))) 
    { 
     // We are already resized and repositioned. 
     return; 
    } 

    // Calculate and apply the toolbar offset 
    const NSInteger delta = 12;  // the difference in size between 44 and 32 px. 
    toolbarFrame.origin.y += ((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) 
           || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)) ? (delta) : (-delta); 
    self.toolbar.frame = toolbarFrame; 

    // Resize the toolbar 
    [[self toolbar] performSelector:@selector(sizeToFit) 
         withObject:nil 
         afterDelay:(0.5f * duration)]; 

} 

@end 

所以,現在我已經正確表現了NavigationBar和Toolbar。最終用戶永遠不會知道我必須實施所有這些額外的解決方案才能重新啓用看起來應該是標準行爲的東西。所以我的問題是,爲什麼我必須做這一切?是否有更好的方法我應該知道,或者我在其他地方沒有做過的事情? (即?[navigationController setAutomaticallyResizesToolbarOnRotate:TRUE];或類似的東西)就像我說的,這似乎像它應該是預接線,所以對我來說,有轉發消息,並被迫觸發器來欺騙的感覺就像一個過度設計的黑客而不是恰當的解決方案。

謝謝!

回答

3

你傳遞的willRotateToInterfaceOrientation消息的標籤視圖控制器從根視圖控制器 - 爲什麼不傳給其他所有的旋轉消息,並看看是否有幫助?即

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    [tabBarController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
} 

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    [tabBarController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { 
    [super didRotateFromInterfaceOrientation:toInterfaceOrientation]; 
    [tabBarController didRotateFromInterfaceOrientation:toInterfaceOrientation]; 
} 

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [super willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    [tabBarController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
} 

- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { 
    [super didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation]; 
    [tabBarController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation]; 
} 

- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [super willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    [tabBarController willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration]; 
} 

我很想看看,如果你通過所有這些你的標籤欄控制器會發生什麼 - 你的問題似乎不是爲你所做的一切額外的工作喜歡的事,應該自動發生,!

+0

是的!這樣可行。實際上,它只需要添加'willAnimateRotationToInterfaceOrientation:'來使其工作。我已經有了willRotate和didRotate。但是,如果您使用'willAnimateRotationToInterfaceOrientation:',則不應使用'willAnimateFirstHalfOfRotationToInterfaceOrientation:'或'willAnimateSecondHalfOfRotationToInterfaceOrientation'。 「didAnimate ...」方法也一樣。無論如何,長話短說,(從字面上)就是這一切。謝謝! :) – quickthyme 2010-10-03 23:03:15