如何同时滑入/滑出statusBar和navigationBar?

发布于 2024-09-06 22:48:51 字数 327 浏览 4 评论 0原文

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

这就是我尝试的方法:

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

但是,两个动画的持续时间并不相同。状态栏动画需要更长的时间。 我找不到如何指定任一动画的持续时间的方法。 我错过了一些明显的事情吗?

I'd like to show and hide the statusBar and the navigationBar simultaneously using a slide effect.

This is how I tried:

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

However, the duration of both animation is not the same. The status bar animation takes longer.
I found no way how to specify the duration of either animation.
Did I miss something obvious?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

入怼 2024-09-13 22:48:51

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];
        }];

    }

}

ios-lizard's answer is almost what I wanted but the navigation bar re-appears when rotating the device unless hidden is set correctly. So this worked for me:

Hidding animating works/looks nice YEAH!!.

Showing animation is OK, (I wish I could make the status bar slide with the navigation bar but at least we don't see gaps anymore. :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];
        }];

    }

}
生生漫 2024-09-13 22:48:51

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

    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];

This is how I fixed this problem for my app.

    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];
柳若烟 2024-09-13 22:48:51

显然,没有简单的解决方案可以正确做到这一点。 Apple 必须修复该问题

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

Clearly, there's no easy solution to do this right. Apple has to fix it.

Of course, one work-around is to use alpha fading as Ephraim suggests. If you're insisting on the sliding behavior, I found it best to just animate the navigation bar and hide/show the statusBar without any animation. This looks much better than sliding the status bar because the gap between the bars during the animation is quite noticeable.

挽清梦 2024-09-13 22:48:51

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

请注意,navigationBar 是一个出口,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];
}

Here's a more concise method that uses system constants for animation duration and also handles incoming calls.

Note that navigationBar is an outlet and statusBarHeight is an instance-variable float.

- (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];
}
走野 2024-09-13 22:48:51

nacho4d的答案几乎是我想要的。但是,他在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];
    }];

在显示的时候,我们希望能够让状态栏随着导航栏一起滑动。 这是我的答案

        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。我们应该先改变navBar的框架,然后使navBar隐藏。
  2. 当显示时,隐藏等于YES。我们首先使导航栏可视化,然后更改框架。
  3. 我们选择UIViewAnimationOptionCurveEaseOut,使其看起来更好。

nacho4d's answer is almost what I wanted .but,He changes navBar's frame before navBar is visible. So we can't see transition animation.It looks like navBar appear suddenly. What is more, when showing, statusBarFrame.size.height is equal to 0. Here is his code:

[[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];
    }];

when Showing , we wish we could make the status bar slide with the navigation bar. here is my answer:

        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. when hidding ,and hidden equal to NO. we should change navBar's frame first,then make navBar hidden.
  2. when showing , and hidden equal to YES. we make navBar visual first,then change frame.
  3. we choose UIViewAnimationOptionCurveEaseOut, to make it looks better.
ペ泪落弦音 2024-09-13 22:48:51

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

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

并实现以下函数:

- (BOOL)prefersStatusBarHidden{
    return _shouldHideStatusBar;
}

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

[self setNeedsStatusBarAppearanceUpdate];

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

- (UIStatusBarAnimation) preferredStatusBarUpdateAnimation {
    return UIStatusBarAnimationSlide;
}

You can use a instance variable to do this:

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

And implement the following function:

- (BOOL)prefersStatusBarHidden{
    return _shouldHideStatusBar;
}

The setNavigationBarHidden:animated function will automatically call prefersStatusBarHidden function. If it doesn't you can call it with the following UIViewController's method:

[self setNeedsStatusBarAppearanceUpdate];

And of course you can choose your status bar hiding animation style with:

- (UIStatusBarAnimation) preferredStatusBarUpdateAnimation {
    return UIStatusBarAnimationSlide;
}
人心善变 2024-09-13 22:48:51

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

// 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 这对我有用

,但如果您找到更好的方法,请在此处发布。

This isn't much of an answer but it works. So what I did is:

// 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];
}

This will basically synchronize the start of the animation (since you are calling setStatusBarHidden at the start of the navigation bar animation. The key part is that the status bar animation seems to take 0.4 seconds.

This works for me but if you find a better way, do post here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文