【问题标题】:How to slide in/out statusBar and navigationBar simultaneously?如何同时滑入/滑出状态栏和导航栏?
【发布时间】:2011-03-09 03:46:06
【问题描述】:

我想使用幻灯片效果同时显示和隐藏状态栏和导航栏。

我就是这样尝试的:

[[UIApplication sharedApplication] setStatusBarHidden:hide withAnimation:UIStatusBarAnimationSlide];
[self.navigationController setNavigationBarHidden:hide animated:animated];

但是,两个动画的持续时间是不一样的。状态栏动画需要更长的时间。 我发现无法指定任一动画的持续时间。 我错过了什么明显的东西吗?

【问题讨论】:

标签: ios iphone cocoa-touch uinavigationcontroller statusbar


【解决方案1】:

ios-lizard 的答案几乎是我想要的,但导航栏会在旋转设备时重新出现,除非 hidden 设置正确。所以这对我有用:

隐藏动画作品/看起来不错耶!!。

显示动画没问题,(我希望我可以让状态栏与导航栏一起滑动,但至少我们看不到差距了。:D)

- (void)toggleFullscreen {

    UINavigationBar *navBar = self.navigationController.navigationBar;
    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    float animationDuration;
    if(statusBarFrame.size.height > 20) { // in-call
        animationDuration = 0.5;
    } else { // normal status bar 
        animationDuration = 0.6;
    }

    _fullscreen = !_fullscreen;
    if (_fullscreen) { 
        // Change to fullscreen mode
        // Hide status bar and navigation bar
        [[UIApplication sharedApplication] setStatusBarHidden:YES
                                                withAnimation:UIStatusBarAnimationSlide];
        [UIView animateWithDuration:animationDuration animations:^{
            navBar.frame = CGRectMake(navBar.frame.origin.x,
                                  -navBar.frame.size.height,
                                  navBar.frame.size.width,
                                  navBar.frame.size.height);
        } completion:^(BOOL finished) {
            [self.navigationController setNavigationBarHidden:YES animated:NO];
        }];

    } else {
        // Change to regular mode
        // Show status bar and navigation bar
        [[UIApplication sharedApplication] setStatusBarHidden:NO
                                                withAnimation:UIStatusBarAnimationSlide];
        [UIView animateWithDuration:animationDuration animations:^{
             navBar.frame = CGRectMake(navBar.frame.origin.x,
                                       statusBarFrame.size.height,
                                       navBar.frame.size.width,
                                       navBar.frame.size.height);
        } completion:^(BOOL finished) {
            [self.navigationController setNavigationBarHidden:NO animated:NO];
        }];

    }

}

【讨论】:

    【解决方案2】:

    这就是我为我的应用解决此问题的方法。

        CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    
        // delta is the amount by which the nav bar will be moved
        delta = statusBarFrame.size.height + self.navigationController.navigationBar.frame.size.height;
    
        if(statusBarFrame.size.height>20) { // in-call
            animationDuration = 0.5;
        }
        else { // normal status bar 
            animationDuration = 0.6;
        }
    
        // hide status bar
        [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
    
        // hide nav bar
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:animationDuration];
    
        self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -delta);
    
        [UIView commitAnimations];
    

    【讨论】:

      【解决方案3】:

      显然,要做到这一点并没有简单的解决方案。苹果必须fix it。

      当然,一种解决方法是按照 Ephraim 的建议使用 alpha 衰减。如果您坚持滑动行为,我发现最好只为导航栏设置动画并隐藏/显示状态栏而不使用任何动画。这看起来比滑动状态栏要好得多,因为动画期间状态栏之间的间隙非常明显。

      【讨论】:

        【解决方案4】:

        这是一个更简洁的方法,它使用系统常量来表示动画持续时间并处理传入的调用。

        注意,navigationBar 是一个 outlet,statusBarHeight 是一个实例变量浮点数。

        - (IBAction)toggleControls:(id)sender {
            BOOL isHidden = ! [UIApplication sharedApplication].statusBarHidden;
            if (isHidden)
                statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
            [UIView animateWithDuration:[UIApplication sharedApplication].statusBarOrientationAnimationDuration animations:^{
                self.navigationBar.frame = CGRectMake(self.navigationBar.frame.origin.x,
                                                      isHidden ? -self.navigationBar.frame.size.height : statusBarHeight,
                                                      self.navigationBar.frame.size.width,
                                                      self.navigationBar.frame.size.height);
            }];
            [[UIApplication sharedApplication] setStatusBarHidden:isHidden withAnimation:UIStatusBarAnimationSlide];
        }
        

        【讨论】:

          【解决方案5】:

          nacho4d 的回答几乎是我想要的。但是,他在 navBar 可见之前改变了 navBar 的框架。所以我们看不到过渡动画。看起来navBar突然出现了。更何况,显示的时候statusBarFrame.size.height等于0。下面是他的代码:

          [[UIApplication sharedApplication] setStatusBarHidden:NO
                                                      withAnimation:UIStatusBarAnimationSlide];
              [UIView animateWithDuration:animationDuration animations:^{
                   navBar.frame = CGRectMake(navBar.frame.origin.x,
                                             statusBarFrame.size.height,
                                             navBar.frame.size.width,
                                             navBar.frame.size.height);
              } completion:^(BOOL finished) {
                  [self.navigationController setNavigationBarHidden:NO animated:NO];
              }];
          

          当 Showing 时,我们希望我们可以使状态栏与导航栏一起滑动。 这是我的答案:

                  UINavigationBar *navBar = self.navigationController.navigationBar;
                  [[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:UIStatusBarAnimationSlide];
          
                  [UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                      // make navigationBar visual
                      if (!hidden)
                      {
                          [self.navigationController setNavigationBarHidden:hidden animated:NO];
                      }
          
                      navBar.frame = CGRectMake(navBar.frame.origin.x,
                                                hidden ? -navBar.frame.size.height : 20,
                                                navBar.frame.size.width,
                                                navBar.frame.size.height);
                  } completion:^(BOOL finished) {
                      if (hidden)
                      {
                          [self.navigationController setNavigationBarHidden:hidden animated:NO];
                      }
                  }];
          
          1. 隐藏时,隐藏等于NO。我们应该先改变导航栏的框架,然后隐藏导航栏。
          2. 显示时,隐藏等于YES。我们先让 navBar 可视化,然后改变框架。
          3. 我们选择UIViewAnimationOptionCurveEaseOut,让它看起来更好。

          【讨论】:

            【解决方案6】:

            您可以使用实例变量来执行此操作:

            self.navigationController setNavigationBarHidden:hide animated:animated];
            _shouldHideStatusBar = hide;
            

            并实现如下功能:

            - (BOOL)prefersStatusBarHidden{
                return _shouldHideStatusBar;
            }
            

            setNavigationBarHidden:animated函数会自动调用prefersStatusBarHidden函数。如果没有,您可以使用以下 UIViewController 的方法调用它:

            [self setNeedsStatusBarAppearanceUpdate];
            

            当然你可以选择你的状态栏隐藏动画样式:

            - (UIStatusBarAnimation) preferredStatusBarUpdateAnimation {
                return UIStatusBarAnimationSlide;
            }
            

            【讨论】:

              【解决方案7】:

              这不是一个很好的答案,但它确实有效。所以我做的是:

              // This method gets called by whatever action you want
              
              - (void) toggleShowStatusNavBars:(id)sender {
              
                  // Assuming you have a ivar called barsHidden
              
                  [UIView beginAnimations:nil context:nil];
                  [UIView setAnimationDuration:0.4]; // This is IMPORTANT, 0.4s
              
                  self.navigationController.navigationBar.alpha = (barsHidden?1.0:0.0);  
              
                  barsHidden = !barsHidden; 
              
                  [UIView setAnimationDelegate:self];
                  [UIView setAnimationWillStartSelector:@selector(setStatusBarHidden)];
              
                  [UIView commitAnimations];
              }
              
              - (void) setStatusBarHidden {
                  [[UIApplication sharedApplication] setStatusBarHidden:barsHidden animated:YES];
              }
              

              这将基本上同步动画的开始(因为您在导航栏动画开始时调用setStatusBarHidden。关键部分是状态栏动画似乎需要0.4秒。

              这对我有用,但如果您找到更好的方法,请在此处发布。

              【讨论】:

              • 您正在使用 Alpha 渐变隐藏导航栏。这更容易,因为在这种情况下,您可以直接操作导航栏。在滑动案例中,我感兴趣的是这不是一种可行的方法,因为 navigationController 还操纵内容视图框架。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-09-01
              • 2013-09-06
              • 1970-01-01
              • 1970-01-01
              • 2015-10-06
              • 1970-01-01
              相关资源
              最近更新 更多