2013-03-03 70 views
4

我有一個可以包含兩個子視圖控制器的自定義視圖控制器。當設備處於縱向方向時,其中一個控制器的視圖變得可見。當設備處於橫向方向時,其他控制器的視圖變爲可見。然而,當橫向取向視圖可見時,狀態欄會縮回以爲特定視圖留出更多空間。設備重新轉換爲縱向模式後,狀態欄不顯示。這是自定義視圖控制器顯示在UINavigationController內。iOS隱藏和取消隱藏狀態欄沒有正確移動子視圖

我的問題是,當狀態欄的可見性變化時,我的子視圖不能正確調整。有最終被一個大的間隙和/或重疊,當開啓設備在不同的取向,如下圖所示: enter image description here

正如你可以看到,它最初是細(縱向),但是當該裝置被關,狀態欄是白色的空白處。當設備轉回肖像時,UINavigationController的導航欄會顯示並與狀態欄重疊,導航欄與其下方視圖之間會出現間隙。如果從一個風景方向到另一個風景方向旋轉180度非常快,則間隙消失並且看起來很好。

下面的方法屬於自定義視圖控制器和willAnimateRotationToInterfaceOrientation:duration:被稱爲(顯然處理旋轉事件)和viewDidAppear:(處理當視圖從以前視圖控制器在被推入導航棧)。

- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear 
{ 
    // Fading animation during orientation flip. 
    // Make sure its not already animating before trying. 
    BOOL barHidden = [UIApplication sharedApplication].statusBarHidden; 
    if (!isAnimating) { 
     BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view); 
     BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view); 
     if ((alreadyGoodGrid && barHidden) || 
      (alreadyGoodTable && !barHidden)) { 
      // If views are the way they should be for this orientation. Don't do 
      // anything. 
      return; 
     } 
     isAnimating = YES; 
     UIView *nextView; 
     // Get starting orientation. This will determine what view goes on top 
     if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) 
      nextView = self.gridViewController.view; 
     else 
      nextView = self.tableViewController.view; 

     if (nextView == self.tableViewController.view) 
     { 
      if (!alreadyGoodTable) 
      { 
       self.tableViewController.view.alpha = 0.0; 
       [self.view bringSubviewToFront:self.tableViewController.view]; 
      } 
      // Unhide the bar for the table view 
      [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; 
     } 
     else // gridViewController 
     { 
      if (!alreadyGoodGrid) 
      { 
       self.gridViewController.view.alpha = 0.0; 
       [self.view bringSubviewToFront:self.gridViewController.view]; 
      } 
      // Hide the bar for the grid view 
      [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; 
     } 
     [UIView animateWithDuration:0.4 
           delay: 0.0 
          options: UIViewAnimationOptionAllowUserInteraction 
         animations:^{ 
          if (nextView == self.tableViewController.view) { 
           self.tableViewController.view.alpha = 1.0; 
          } 
          else { 
           self.gridViewController.view.alpha = 1.0; 
          }        
         } 
         completion:^(BOOL finished) { 
          if (nextView == self.tableViewController.view) { 
           curView = self.tableViewController.view; 
          } 
          else { 
           curView = self.gridViewController.view; 
          } 
          isAnimating = NO; 
         }]; 
    } 
} 

非常感謝任何人,可以花時間看看這個。

回答

2

很多人似乎都有這個問題,因爲我有,而且還有其他有關它的Q/A線索,你應該尋找 - 我可能永遠找不到神奇的答案。在某些情況下,您可能會試圖解決問題的一種方法是在將條形可見性更改爲(重新)顯示狀態條時:

  • 隱藏導航欄。
  • 取消隱藏狀態欄。
  • 取消隱藏導航欄。

或隱藏,隱藏,取消隱藏如果你隱藏狀態欄。

有時候人們發現在隱藏導航欄之前需要略微延遲 - 所以在異步調度塊中在下一個runloop上運行。例如:

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.navigationController setNavigationBarHidden:NO animated:NO]; 
}); 
+0

感謝您的幫助。對你有好處。我確實得到了另一個解決方案,似乎很好,我只是作爲答案發布。 – 2013-03-04 03:40:57

+0

很高興你找到了一些東西 - 也許它會幫助我! – 2013-03-04 16:12:46

0

在擺弄了很多東西之後,我似乎想出了一些解決方案。它似乎工作沒有失敗。

這裏是我的代碼:

- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear 
{ 
    // Fading animation during orientation flip. 
    // Make sure its not already animating before trying. 
    BOOL barHidden = [UIApplication sharedApplication].statusBarHidden; 
    if (!isAnimating) { 
     BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view); 
     BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view); 
     if ((alreadyGoodGrid && barHidden) || 
      (alreadyGoodTable && !barHidden)) { 
      // If views are the way they should be for this orientation. Don't do 
      // anything. 
      return; 
     } 
     isAnimating = YES; 
     UIView *nextView; 
     // Get starting orientation. This will determine what view goes on top 
     if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) 
      nextView = self.gridViewController.view; 
     else 
      nextView = self.tableViewController.view; 

     if (nextView == self.tableViewController.view) 
     { 
      if (!alreadyGoodTable) 
      { 
       self.tableViewController.view.alpha = 0.0; 
       [self.view bringSubviewToFront:self.tableViewController.view]; 
      } 
      [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; 
     } 
     else 
     { 
      if (!alreadyGoodGrid) 
      { 
       self.gridViewController.view.alpha = 0.0; 
       [self.view bringSubviewToFront:self.gridViewController.view]; 
      } 
      [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; 
     } 
     [UIView animateWithDuration:0.4 
           delay: 0.0 
          options: UIViewAnimationOptionAllowUserInteraction 
         animations:^{ 
          CGRect r = self.navigationController.navigationBar.frame; 
          if (nextView == self.tableViewController.view) { 
           self.tableViewController.view.alpha = 1.0; 
           self.navigationController.navigationBar.frame = CGRectMake(0.0, 20.0, r.size.width, r.size.height); 
           self.view.frame = CGRectMake(0.0, 20.0, self.view.frame.size.width, self.view.frame.size.height - 20.0); 

          } 
          else { 
           self.gridViewController.view.alpha = 1.0; 
           self.navigationController.navigationBar.frame = CGRectMake(0.0, 0.0, r.size.width, r.size.height); 
           double y = 0.0, h = 0.0; 
           if (fromViewDidAppear) 
           { 
            y = -20.0; 
            h = 20.0; 
           } 
           self.view.frame = CGRectMake(0.0, y, self.view.frame.size.width, self.view.frame.size.height + h); 
          }        
         } 
         completion:^(BOOL finished) { 
          if (nextView == self.tableViewController.view) { 
           curView = self.tableViewController.view; 
          } 
          else { 
           curView = self.gridViewController.view; 
          } 
          isAnimating = NO; 
         }]; 
    } 
} 

我要做的就是檢查是否該方法正在從viewDidAppear:叫或其他地方(在這種情況下,只有willAnimateRotationToInterfaceOrientation:duration:)。取決於誰調用方法,情況會有所不同。在任何一種情況下,我都會調整self.view.frameself.navigationController.navigationBar.frame以解決狀態欄位置的差異。當我們來自viewDidAppear:我需要拋出狀態欄高度的負y值,以使子視圖正常向上移動。這似乎都似乎工作得很好。

0

我在隱藏狀態欄和導航欄重疊後出現同樣的問題,然後再次顯示。我在github here(見showUI方法)上找到了一個解決方案,我修改了它以適合我的需要。

- (void)toggleNavBar:(BOOL)hide 
{  
    navBarHidden = hide; 

    //Fade status bar 
    [[UIApplication sharedApplication] setStatusBarHidden:hide 
              withAnimation:UIStatusBarAnimationFade]; 

    //Fade navigation bar 
    [UINavigationBar beginAnimations:nil context:nil]; 
    [UIView setAnimationDuration:0.3]; // Approximately the same time the status bar takes to fade. 

    self.navigationController.navigationBar.alpha = hide ? 0 : 1; 

    [UINavigationBar commitAnimations]; 

    // Being invisible messes with the position of the navigation bar, every time it gets 
    // visible we need to set it to the correct y-offset (just below the status bar) 
    [self adjustNavBarOrigin]; 
} 

-(void)adjustNavBarOrigin 
{ 
    CGRect r = self.navigationController.navigationBar.frame; 
    r.origin.y = 20; //Height of the statusbar, can't find a reliable method in the SDK to get this value 
    self.navigationController.navigationBar.frame = r; 
} 
0

爲ios7,覆蓋prefersStatusBarHidden

- (BOOL)prefersStatusBarHidden { 
    return NO if landscape and NO if landscape; 
} 

的方向變化調用函數低於觸發prefersStatusBarHidden功能

[self setNeedsStatusBarAppearanceUpdate]; 

看到https://stackoverflow.com/a/19194901/1939554

0

這解決了詳細的解答我的問題:

self.automaticallyAdjustsScrollViewInsets = false 
+0

你能否在你的回答中解釋爲什麼它解決了你的問題? – Zulu 2014-11-29 01:27:38

+0

我的問題是,當我試圖在包含子視圖的視圖中隱藏導航/狀態欄時,子視圖將隨頂部欄移動。最近我發現問題與插入設置。 – 2014-11-29 01:47:41