如何在不隐藏状态栏的情况下淡出状态栏

时间:2014-01-06 01:58:28

标签: iphone objective-c cocoa-touch animation ios7

iOS开发者肯定会知道有关状态栏和着名的“幻灯片/汉堡包/抽屉”的问题。这个问题在这里得到了很好的解释:http://uxmag.com/articles/adapting-ui-to-ios-7-the-side-menu

我正在使用MMDrawerController库,它有一个很好的黑客,让我们可以在容器视图控制器上方创建一个虚拟状态栏。不幸的是,这不是很好。有什么新的消息?新闻是我偶然发现了一个应用程序(Tinder),完美地解决了这个令人兴奋的问题。我创建了一个完美展示Tinder所做的GIF。

enter image description here

需要等待几秒钟才能看到gif,因为它有一个错误而且我不知道如何摆脱它。只需等待一两秒钟就能正确看到gif。


无论如何,Tinder做什么?当用户点击左上方的菜单按钮并开始向右滑动时,状态栏整齐地淡出。当视图恢复到原始位置时,状态栏将再次显示。

我为此感到高兴和有点难过,因为这意味着必须才能做到这一点,但我真的不知道如何实现它(可能是黑客MMDrawerController )。任何帮助都将非常感激。


重要

请注意方法setStatusBarHidden:将完全隐藏状态栏,这意味着整个视图的高度为-20px。这显然不是解决方案,因为从gif可以看出视图没有被拉伸。

5 个答案:

答案 0 :(得分:21)

您的主要问题是MMDrawerController。如果你要深入了解它,你会发现许多与状态栏相关的方法,例如setShowsStatusBarBackgroundView setStatusBarViewBackgroundColor等等。当状态栏被隐藏时,代码中的某些内容会推动视图。

或者,您可以使用其他抽屉控制器或使用自定义代码。

以下是如何实现这一目标的简单方法:

enter image description here

ViewControllerA:

-(BOOL)prefersStatusBarHidden
{
    return _hidden;
}
- (void)statusHide
{
    [UIView animateWithDuration:0.4 animations:^() {[self setNeedsStatusBarAppearanceUpdate];
    }completion:^(BOOL finished){}];
}

ViewControllerB :( ViewControllerA中的容器)

- (IBAction)move:(UIButton *)sender
{
    parent = (ViewController*)self.parentViewController;
    parent.hidden = !parent.hidden;
    CGRect frame = parent.blueContainer.frame;
    if(parent.hidden)
    {
        frame.origin.x = 150;
    }
    else
    {
        frame.origin.x = 0;
    }

    [UIView animateWithDuration:1 animations:^() {parent.blueContainer.frame = frame;}completion:^(BOOL finished){}];
    [parent statusHide];
}

对于iOS 6 compatieblty使用:

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

表格视图和其他子视图将保留在其位置,并且不会被推高。

修改

添加NavigationBar:

  

UINavigationController会将其UINavigationBar的高度更改为   无论是44分还是64分,取决于一个相当奇怪的和   未记录的约束集。如果UINavigationController检测到   它的视图框架的顶部在视觉上与其相邻   UIWindow的顶部,然后它绘制高度为64的导航栏   点。如果它的视图顶部与UIWindow的顶部不相邻   (即使只关闭一个点),然后它会绘制导航栏   高度为44分的“传统”方式。这个逻辑是   由UINavigationController执行,即使它是几个孩子   在应用程序的视图控制器层次结构内。那里   无法阻止这种行为。

取自here

您可以简单地将UINavigationController子类化并创建自己的导航栏以避免这种烦恼。

答案 1 :(得分:5)

我不知道它是否能解决你的问题,但我使用SWRevealViewController项目得到了几乎相同的效果。在appDelegate中,我从这个类中设置了委托方法来执行此操作:

- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position {
#ifdef DEBUG
    NSArray *teste = @[@"FrontViewPositionLeftSideMostRemoved",@"FrontViewPositionLeftSideMost",@"FrontViewPositionLeftSide",@"FrontViewPositionLeft",@"FrontViewPositionRight",@"FrontViewPositionRightMost",@"FrontViewPositionRightMostRemoved"];
    NSLog(@"%@ %d", teste[position], position);
#endif
    if (position == FrontViewPositionRight)
        [[UIApplication sharedApplication] setStatusBarHidden:YES  withAnimation:UIStatusBarAnimationFade];
    UINavigationController *frontViewController = (id)revealController.frontViewController;
    frontViewController.navigationBar.centerY += (position == FrontViewPositionRight) ?  20 : 0; //  20 == statusbar heihgt
}

- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position {
    if (position == FrontViewPositionLeft)
        [[UIApplication sharedApplication] setStatusBarHidden:NO  withAnimation:UIStatusBarAnimationFade];
}

centerY是UIView中的一个类别,它设置center.y而不处理设置框架变量的无聊部分。

答案 2 :(得分:3)

以下是在iOS 7中应该如何做到这一点:

@implementation ViewController
{
    BOOL _hideStatusBar;
}

-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleDefault;
}

-(UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
    return UIStatusBarAnimationFade;
}

-(BOOL)prefersStatusBarHidden
{
    return _hideStatusBar;
}

-(void)setStatusBarHidden:(BOOL)hidden
{
    [UIView animateWithDuration:1.0 animations:^{
        _hideStatusBar = hidden;
        [self setNeedsStatusBarAppearanceUpdate];
    }];
}

@end

答案 3 :(得分:1)

查看setStatusBarHidden:withAnimation:上的方法UIApplication。它允许您显示或隐藏状态栏,动画可以是无,淡入淡出或幻灯片。你只需要添加一个隐藏栏的调用,然后在正确的时间显示一个栏,并确定你是否喜欢你所说明的淡入淡出或幻灯片是否适合你。

https://developer.apple.com/library/ios/DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/UIApplication/setStatusBarHidden:withAnimation

答案 4 :(得分:1)

如果您在-setStatusBarHidden:withAnimation:中调整视图框,则可以使用-viewDidAppear:,然后您将看不到任何拉伸。 请注意,自动布局已禁用。

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    CGRect frame = self.view.frame;
    // adjust root view frame 
    frame.origin.y -= 20;
    frame.size.height += 20;

    [self.view setFrame:frame];

    // adjust subviews y position
    for (UIView *subview in [self.view subviews])
    {
        CGRect frame = subview.frame;
        frame.origin.y += 20;
        [subview setFrame:frame];
    }
}

- (IBAction)sliderChanged:(id)sender
{
    UISlider *s = (UISlider *)sender;
    if (s.value > .5)
    {
        UIApplication *app = [UIApplication sharedApplication];
        if (![app isStatusBarHidden])
            [app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
    }
    else
    {
        UIApplication *app = [UIApplication sharedApplication];
        if ([app isStatusBarHidden])
            [app setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
    }
}

enter image description here