如何在iOS7中使用淡入淡出效果切换状态栏(如照片应用)?

时间:2013-10-01 19:51:09

标签: objective-c ios7 statusbar

我想点击状态栏的可见性,就像在照片应用中一样。

在iOS 7之前,此代码运行良好:

-(void)setStatusBarIsHidden:(BOOL)statusBarIsHidden {

    _statusBarIsHidden = statusBarIsHidden;

    if (statusBarIsHidden == YES) {

        [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];


    }else{

        [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];

    }

}

但是我无法在iOS 7中使用它。我发现的所有答案都只提供永久隐藏栏但不切换的建议。

然而,必须有一种方式,因为照片做到了。

8 个答案:

答案 0 :(得分:44)

默认情况下,在iOS 7或更高版本上,要隐藏特定视图控制器的状态栏,请执行以下操作:

  1. 如果要隐藏状态栏的视图控制器以模态方式呈现且modalPresentationStyle不是UIModalPresentationFullScreen,请在呈现时手动将modalPresentationCapturesStatusBarAppearance设置为YES控制器在呈现之前(例如,如果您使用的是故事板,则在-presentViewController:animated:completion-prepareForSegue:中)
  2. 在显示的控制器中覆盖-prefersStatusBarHidden并返回适当的值
  3. 在呈现的控制器上调用setNeedsStatusBarAppearanceUpdate
  4. 如果要为其外观或消失设置动画,请在动画块中执行第三步:

    [UIView animateWithDuration:0.33 animations:^{
        [self setNeedsStatusBarAppearanceUpdate];
    }];
    

    您还可以通过在显示的控制器中从UIStatusBarAnimation返回适当的-preferredStatusBarUpdateAnimation值来设置动画样式。

答案 1 :(得分:6)

首先将Info.plist中的View controller-based status bar appearance设置为YES

此Swift示例显示了在按下按钮后如何使用动画切换StatusBar。

import UIKit

class ToggleStatusBarViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func prefersStatusBarHidden() -> Bool {
        return !UIApplication.sharedApplication().statusBarHidden
    }

    override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
        return UIStatusBarAnimation.Slide
    }

    @IBAction func toggleStatusBar(sender: UIButton) {
        UIView.animateWithDuration(0.5,
            animations: {
                self.setNeedsStatusBarAppearanceUpdate()
        })
    }
}

答案 2 :(得分:5)

我能够简化@ Jon的答案,并且仍然可以与iOS 7上的照片应用程序区分开来。看起来像展示时的延迟更新是不必要的。

- (IBAction)toggleUI:(id)sender {
    self.hidesUI = !self.hidesUI;

    CGRect barFrame = self.navigationController.navigationBar.frame;

    CGFloat alpha = (self.hidesUI) ? 0.0 : 1.0;
    [UIView animateWithDuration:0.33 animations:^{
        [self setNeedsStatusBarAppearanceUpdate];
        self.navigationController.navigationBar.alpha = alpha;
    }];

    self.navigationController.navigationBar.frame = CGRectZero;
    self.navigationController.navigationBar.frame = barFrame;
}

- (BOOL)prefersStatusBarHidden {
    return self.hidesUI;
}

答案 3 :(得分:4)

这可能被认为是一个黑客,但它是我最接近再现效果。还有一个小问题。淡出时,您可以看到导航栏从顶部调整大小。这是微妙的,但仍然不是一个完美的褪色。如果有人知道如何解决它,请告诉我!

- (BOOL)prefersStatusBarHidden {

    if (_controlsAreHidden == YES)
        return YES;
    else
        return NO;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {

    return UIStatusBarAnimationFade;
}

-(void)setControlsAreHidden:(BOOL)controlsAreHidden {

    _controlsAreHidden = controlsAreHidden;

    if (controlsAreHidden == YES) {

        // fade out
        //

        CGRect barFrame = self.navigationController.navigationBar.frame;

        [UIView animateWithDuration:0.3 animations:^ {


            [self setNeedsStatusBarAppearanceUpdate];

            self.navigationController.navigationBar.alpha = 0;



        }];


        self.navigationController.navigationBar.frame = CGRectMake(0, 20, barFrame.size.width, 44);



    }else{


        // fade in
        //

        CGRect barFrame = self.navigationController.navigationBar.frame;

        self.navigationController.navigationBar.frame = CGRectMake(0, 20, barFrame.size.width, 64);

        [UIView animateWithDuration:0.3 animations:^ {

            [self setNeedsStatusBarAppearanceUpdate];

            self.navigationController.navigationBar.alpha = 1;

        }];


    }

}

答案 4 :(得分:3)

此代码完美无缺:

-(void)setControlsAreHidden:(BOOL)controlsAreHidden {

    if (_controlsAreHidden == controlsAreHidden)
        return;

    _controlsAreHidden = controlsAreHidden;


    UINavigationBar * navigationBar = self.navigationController.navigationBar;

    if (controlsAreHidden == YES) {

        // fade out
        //

        CGRect barFrame = self.navigationController.navigationBar.frame;

        [UIView animateWithDuration:0.3 animations:^ {
            [self setNeedsStatusBarAppearanceUpdate];
            self.navigationController.navigationBar.alpha = 0;
        }];

        self.navigationController.navigationBar.frame = CGRectZero;
        self.navigationController.navigationBar.frame = CGRectMake(0, 20, barFrame.size.width, 44);

    } else {

        // fade in
        //
        [UIView animateWithDuration:UINavigationControllerHideShowBarDuration animations:^ {
            [self setNeedsStatusBarAppearanceUpdate];
        }];

        double delayInSeconds = 0.01;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

            [self.navigationController setNavigationBarHidden:NO animated:NO];
            navigationBar.alpha = 0;
            [UIView animateWithDuration:UINavigationControllerHideShowBarDuration animations:^ {
                navigationBar.alpha = 1;
            }];

        });

    }

}

答案 5 :(得分:3)

实际上现在需要弄乱导航条框架。只需使用2个独立的动画块即可实现平滑动画。像这样的东西应该可以正常工作。

@property (nonatomic, assign) BOOL controlsShouldBeHidden;

...

- (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated {

    if (self.controlsShouldBeHidden == hidden) {
        return;
    }

    self.controlsShouldBeHidden = hidden;

    NSTimeInterval duration = animated ? 0.3 : 0.0;

    [UIView animateWithDuration:duration animations:^(void) {

        [self setNeedsStatusBarAppearanceUpdate];

    }];

    [UIView animateWithDuration:duration animations:^(void) {

        CGFloat alpha = hidden ? 0 : 1;
        [self.navigationController.navigationBar setAlpha:alpha];

    }];

}

- (BOOL)prefersStatusBarHidden {

    return self.controlsShouldBeHidden;

}

为了与iOS 6兼容,请务必检查[self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]

答案 6 :(得分:1)

解决此问题的方法取决于应用程序plist中“基于视图控制器的状态栏外观”设置的值。

如果您的plist中的“查看基于控制器的状态栏外观”为NO,则此代码应该有效:

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];

如果启用了“查看基于控制器的状态栏外观”,则在视图控制器中添加以下方法:

- (BOOL) prefersStatusBarHidden {
    // I've hardcoded to YES here, but you can return a dynamic value to meet your needs for toggling
    return YES;
}

对于切换,当您想要根据上述方法的值更改是否隐藏/显示状态栏时,视图控制器可以调用setNeedsStatusBarAppearanceUpdate方法。

答案 7 :(得分:1)

要解决此问题,导航栏在淡入淡出时向上滑动,您应添加以下代码:

self.navigationController.navigationBar.frame = CGRectZero;

进入以下代码行之前的“淡入”部分:

self.navigationController.navigationBar.frame = CGRectMake(0, 20, barFrame.size.width, 64);

这是必要的,因为框架是相同的,设置相同的框架将被忽略,并且不会阻止导航栏滑动。因此,您需要将帧更改为不同的帧,然后再将其设置为正确的帧以触发更改。