如何在应用程序之外的屏幕底部显示应用程序特定的状态栏?

时间:2012-05-14 17:40:13

标签: ios ipad

我要求在我的应用程序底部的某些时间显示状态栏。我可以很容易地将它放在我的应用程序主视图的底部,但每当我在其上推动一个视图控制器时(无论是否是模态)都隐藏了这个状态栏。

有没有办法可以添加这样的状态栏,让它超出我的应用程序本身的范围?理想情况下,我希望这可以像iPhone上的呼叫状态栏一样工作 - 当此栏出现时,应用程序被按下,并且对[[UIScreen mainScreen] applicationFrame]的呼叫返回正确的大小(即它占在计算应用程序的可用高度时,是否存在此状态栏。

1 个答案:

答案 0 :(得分:1)

我也想这样做,所以我尝试View Controller Containment。我还在尝试,所以我不愿意给予这个响当的代言,但如果你在iOS5中,那么你可能想尝试一下自己。但它似乎会给你一个状态栏,它会从屏幕底部显示或消失。

这是一个视图控制器,它将打开另一个视图控制器,但如果有要显示的状态文本,它将从屏幕底部弹出并保持在那里直到你摆脱它。到目前为止我只进行了一些测试,但它看起来像处理pushViewController / popViewController,但可能不是模态视图。

我的标题如下:

//  StatusBarViewController.h
//
//  Created by Robert Ryan on 7/8/12.

#import <UIKit/UIKit.h>

@interface StatusBarViewController : UIViewController

@property (strong, nonatomic) UIViewController *appController;

- (void)setStatus:(NSString *)text;

@end

我的实施文件(这是ARC)如下所示:

//  StatusBarViewController.m
//
//  Created by Robert Ryan on 7/8/12.

#import "StatusBarViewController.h"

@interface StatusBarViewController ()
{
    BOOL _statusHidden;
    UIView *_appView;
    UILabel *_statusLabel;
}
@end

@implementation StatusBarViewController

@synthesize appController = _appController;

- (void)dealloc
{
    _appView = nil;
    _statusLabel = nil;

    [self setAppController:nil]; // usually I don't like setters in dealloc, but this does some special stuff
}

- (void)createControlsWithStatusHidden
{
    // create default app view that takes up whole screen

    CGRect frame = self.view.frame;
    frame.origin = CGPointMake(0.0, 0.0);
    _appView = [[UIView alloc] initWithFrame:frame];
    _appView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    _appView.clipsToBounds = YES;
    [self.view addSubview:_appView];

    // create status label that is just off screen below the app view

    _statusLabel = [[UILabel alloc] init];
    _statusLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:12.0];
    _statusLabel.backgroundColor = [UIColor darkGrayColor];
    _statusLabel.textColor = [UIColor whiteColor];
    CGSize size = [@"Hey!" sizeWithFont:_statusLabel.font]; // test size of box with random text
    _statusLabel.frame = CGRectMake(0.0, frame.size.height, frame.size.width, size.height);
    _statusLabel.textAlignment = UITextAlignmentCenter;
    _statusLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    [self.view addSubview:_statusLabel];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self createControlsWithStatusHidden];
    _statusHidden = YES;

    // I'm instantiating from storyboard. If you're using NIBs, just create your controller controller using initWithNib and then set our appController accordingly.

    self.appController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainNavigator"];
}

- (void)setAppController:(UIViewController *)controller
{
    if (controller)
    {
        controller.view.frame = CGRectMake(0.0, 0.0, _appView.frame.size.width, _appView.frame.size.height);
        [self addChildViewController:controller];
        [controller didMoveToParentViewController:self];

        if (self.appController)
        {
            // if we have both a new controller and and old one, then let's transition, cleaning up the old one upon completion

            [self transitionFromViewController:self.appController
                              toViewController:controller
                                      duration:0.5 
                                       options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveEaseInOut
                                    animations:nil
                                    completion:^(BOOL finished){
                                        if (self.appController)
                                        {
                                            [self.appController willMoveToParentViewController:nil];
                                            [self.appController removeFromParentViewController];
                                        }
                                    }];
        }
        else 
        {
            // if we have no previous controller (i.e. this is our first rodeo), then just add it to the view

            [_appView addSubview:controller.view];
        }
    }
    else
    {
        // no new controller, so we're just removing any old on if it was there

        if (self.appController)
        {
            // if there was an old controller, remove it's view, and remove it from the view controller hierarchy

            [self.appController.view removeFromSuperview];
            [self.appController willMoveToParentViewController:nil];
            [self.appController removeFromParentViewController];
        }
    }

    _appController = controller;
}

- (void)hideStatusWithCompletion:(void (^)(BOOL finished))completion
{
    [UIView animateWithDuration:0.25 
                     animations:^{
                         CGRect labelFrame = _statusLabel.frame;
                         labelFrame.origin.y += labelFrame.size.height;
                         _statusLabel.frame = labelFrame;

                         CGRect appFrame = _appView.frame;
                         appFrame.size.height += labelFrame.size.height;
                         _appView.frame = appFrame;
                     }
                     completion:completion];
}

- (void)unhideStatusWithCompletion:(void (^)(BOOL finished))completion
{
    [UIView animateWithDuration:0.25 
                     animations:^{
                         CGRect labelFrame = _statusLabel.frame;
                         labelFrame.origin.y -= labelFrame.size.height;
                         _statusLabel.frame = labelFrame;

                         CGRect appFrame = _appView.frame;
                         appFrame.size.height -= labelFrame.size.height;
                         _appView.frame = appFrame;
                     }
                     completion:completion];
}

- (void)setStatus:(NSString *)text
{
    BOOL hasText = (text && [text length] > 0);

    if (hasText)
    {
        if (!_statusHidden)
        {
            // if we have text, but status is already shown, then hide it and unhide it with new value

            [self hideStatusWithCompletion:^(BOOL finished){
                _statusLabel.text = text;
                [self unhideStatusWithCompletion:nil];
            }];
        }
        else
        {
            // if we have text, but no status is currently shown, then just unhide it
            _statusLabel.text = text;
            [self unhideStatusWithCompletion:nil];
        }
        _statusHidden = NO;
    }
    else
    {
        if (!_statusHidden)
        {
            // if we don't have text, but status bar is shown, then just hide it

            [self hideStatusWithCompletion:^(BOOL finished){
                _statusLabel.text = text;
            }];
            _statusHidden = YES;
        }
    }
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

然后,任何想要更新状态消息的视图控制器都会使用类似的方法:

- (void)setStatus:(NSString *)text
{
    UIViewController *controller = [UIApplication sharedApplication].delegate.window.rootViewController;

    if ([controller isKindOfClass:[StatusBarViewController class]])
    {
        [(StatusBarViewController *)controller setStatus:text];
    }
}