在Facebook新的iOS7应用程序中,UIStatusBar是什么意思?

6

我有一个带侧边栏菜单的应用程序,有点像Facebook侧边栏菜单。我正在使用这个名为SWRevealViewController的类,效果很好。现在由于iOS7已经推出,我就无法想出如何调整我的状态栏和导航栏,使其像Facebook应用程序那样。

正如您所看到的,在Facebook应用程序中,当用户滑动屏幕并打开菜单时,状态栏会从导航栏蓝色变成黑色,并带有淡入淡出的动画。但在我的应用程序中,用户滑动屏幕以打开菜单时,状态栏保持蓝色(因为该视图的NavigationBar是蓝色),不会消失并变成黑色。

facebook app navigation bar

my app navigation bar

此外,我还遇到了另一个问题,我无法将StatusBar文本颜色更改为白色。我尝试了所有互联网上的代码,阅读了苹果的所有文档,但仍然无法成功更改颜色。

我也使用了这段代码:

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
    return UIStatusBarAnimationFade;
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

- (BOOL)prefersStatusBarHidden
{
    return NO;
}

提前感谢。

========================================================================

更新:像 @yoeriboven 回答中所述,解决此问题的方法是在SWRevealViewController上方放置两个视图,一个黑色和一个蓝色,并对这两个视图进行动画处理,这是一个很好的解决方案,它非常有效。

因此,在创建revealController时,我创建了2个空白的UIView并将它们添加到上面,一个是蓝色的,一个是黑色的。其中一个黑色的UIView目前被隐藏了。

self.revealController = [[SWRevealViewController alloc] initWithRearViewController:nil frontViewController:self.frontViewController];
self.revealController.delegate = self;

self.appDelegate.window.rootViewController = self.revealController;

self.statusBarBlack = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.appDelegate.window.frame.size.width, 20)];
[self.statusBarBlack setBackgroundColor:[UIColor blackColor]];

self.statusBarBlue = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.appDelegate.window.frame.size.width, 20)];
[self.statusBarBlue setBackgroundColor:[UIColor blueColor]];

[self.appDelegate.window.rootViewController.view addSubview:self.statusBarBlack];
[self.appDelegate.window.rootViewController.view addSubview:self.statusBarBlue];

如果您正在使用SWRevealViewController,您可以使用下面的代码。如果没有,请自己构建,在SWRevealViewController.m中导入#import "AppDelegate.h",然后用以下方法替换touchesMoved方法:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];

    if (self.state == UIGestureRecognizerStateFailed)
        return;

    //  Change color of status bar by the location of your swipe
    AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    UITouch *currentTouch = [touches anyObject];
    CGPoint currentTouchLocationOnWindow = [currentTouch locationInView:appDelegate.window];
    appDelegate.splashScreen.blueStatusBar.alpha = currentTouchLocationOnWindow.x / appDelegate.window.frame.size.width;

    if ( _dragging )
        return;

    const int kDirectionPanThreshold = 5;

    UITouch *touch = [touches anyObject];
    CGPoint nowPoint = [touch locationInView:self.view];

    CGFloat moveX = nowPoint.x - _init.x;
    CGFloat moveY = nowPoint.y - _init.y;

    if (abs(moveX) > kDirectionPanThreshold)
    {
        if (_direction == SWDirectionPanGestureRecognizerHorizontal)
            _dragging = YES;
        else
            self.state = UIGestureRecognizerStateFailed;
    }
    else if (abs(moveY) > kDirectionPanThreshold)
    {
        if (_direction == SWDirectionPanGestureRecognizerVertical)
            _dragging = YES ;
        else
            self.state = UIGestureRecognizerStateFailed;
    }
}

现在向下滚动一点,查找方法rightRevealToggleAnimated并将其替换为以下内容:

- (void)rightRevealToggleAnimated:(BOOL)animated
{
    FrontViewPosition toogledFrontViewPosition = FrontViewPositionLeft;
    if (_frontViewPosition >= FrontViewPositionLeft) {
        toogledFrontViewPosition = FrontViewPositionLeftSide;
        [UIView animateWithDuration:0.3 animations:^{
            //  Change color of status bar
            AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
            appDelegate.splashScreen.blueStatusBar.alpha = 0.0;
        }];
    } else {
        [UIView animateWithDuration:0.3 animations:^{
            //  Change color of status bar
            AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
            appDelegate.splashScreen.blueStatusBar.alpha = 1.0;
        }];
    }

    [self setFrontViewPosition:toogledFrontViewPosition animated:animated];
}

那应该就可以了,享受吧!

更改状态栏样式时,不要忘记在呈现的视图控制器上调用 setNeedsStatusBarAppearanceUpdate - Léo Natan
我在viewDidLoad方法中调用它,仍然是一样的。 - ytpm
我不确定这是正确的位置。请尝试在viewDidAppear中。 - Léo Natan
将其放置在viewDidAppear和viewWillAppear中,但仍然得到相同的结果。 - ytpm
3个回答

7
在iOS 7中,您的视图控制器视图是全屏的。因此,您可以将两个视图放在视图的顶部22像素(状态栏高度)上方。底部为黑色,顶部与导航栏颜色相同。当向 SWRevealViewController 滑动时,使用其中一个 UIScrollView 委托方法可以计算百分比距离,并将该值应用于具有导航栏颜色的子视图的不透明度。

这是一个很棒的解决方案,我已经更新了我的答案,以便那些也需要它的人可以使用。谢谢! - ytpm
很高兴能帮到你。如果您确认我的答案是正确的,那就太棒了。祝您的项目好运。 - yoeriboven

3
我有另一种方法也非常有效。
首先,在 SWRevealViewController.h 文件中的 SWRevealView 类中,我创建了一个名为 underStatusBarView 的 View @property,并将其放置在状态栏位置。
然后,在 - (id)initWithFrame:(CGRect)frame controller:(SWRevealViewController*)controller 方法中,我实例化了该 @property,并将其颜色设置为黑色,透明度设置为 0。
- (id)initWithFrame:(CGRect)frame controller:(SWRevealViewController*)controller
{
    self = [super initWithFrame:frame];
    if ( self )
    {
        _c = controller;
        CGRect bounds = self.bounds;

        _frontView = [[UIView alloc] initWithFrame:bounds];
        _frontView.autoresizingMask =   UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;

        [self addSubview:_frontView];

        CALayer *frontViewLayer = _frontView.layer;
        frontViewLayer.masksToBounds = NO;
        frontViewLayer.shadowColor = [UIColor blackColor].CGColor;

        /* Here starts my under status bar implementation */
        CGRect statusFrame = [[UIApplication sharedApplication]statusBarFrame];
        _underStatusBarView = [[UIView alloc]initWithFrame:statusFrame];
        [_underStatusBarView setBackgroundColor:[UIColor blackColor]];
        [_underStatusBarView setAlpha:0.0];
        [self addSubview:_underStatusBarView];
        /* here it ends */

        //frontViewLayer.shadowOpacity = 1.0f;
        frontViewLayer.shadowOpacity = _c.frontViewShadowOpacity;
        frontViewLayer.shadowOffset = _c.frontViewShadowOffset;
        frontViewLayer.shadowRadius = _c.frontViewShadowRadius;
    }

    return self;
}

然后我在负责布置后视图的私有方法- (void)_layoutRearViewsForLocation:(CGFloat)xLocation中添加了一行代码,根据前视图位置来更改_underStatusBarView的透明度。

- (void)_layoutRearViewsForLocation:(CGFloat)xLocation
{
    CGRect bounds = self.bounds;

    CGFloat rearRevealWidth = _c.rearViewRevealWidth;
    if ( rearRevealWidth < 0) rearRevealWidth = bounds.size.width + _c.rearViewRevealWidth;

    CGFloat rearXLocation = scaledValue(xLocation, -_c.rearViewRevealDisplacement, 0, 0, rearRevealWidth);

    CGFloat rearWidth = rearRevealWidth + _c.rearViewRevealOverdraw;
    _rearView.frame = CGRectMake(rearXLocation, 0.0, rearWidth, bounds.size.height);

    CGFloat rightRevealWidth = _c.rightViewRevealWidth;
    if ( rightRevealWidth < 0) rightRevealWidth = bounds.size.width + _c.rightViewRevealWidth;

    CGFloat rightXLocation = scaledValue(xLocation, 0, _c.rightViewRevealDisplacement, -rightRevealWidth, 0);

    CGFloat rightWidth = rightRevealWidth + _c.rightViewRevealOverdraw;
    _rightView.frame = CGRectMake(bounds.size.width-rightWidth+rightXLocation, 0.0f, rightWidth, bounds.size.height);

    /*this line changes the under status bar view alpha*/
   _underStatusBarView.alpha = xLocation/rearRevealWidth;
}

在使用 rightRevealView 时,您应该将 rearRevealWidth 更改为 rightRevealWidth,以避免未来的兼容性问题。


这在竖屏方向上运行得很好,但当我在iPad上切换到横屏方向时,当后置视图被显示出来时,黑色状态栏并没有完全覆盖在屏幕顶部。我该如何解决这个问题? - user2330922

0

我真的很喜欢你的方法。我对你的代码进行了一些更新,并想将其提交到项目中。如果你对我这样做有任何问题,请告诉我。


请使用注释回复此类回复,不要使用答案。 - markcial
我尝试了。不幸的是,要评论别人的答案,您必须至少拥有50的声望。 - dppeak
如果可以,请使用其他渠道,最好保持问题回复较少,以免混淆谷歌或寻找答案的人,谢谢。 - markcial

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接