1

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

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

4

1 回答 1

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];
    }
}
于 2012-07-08T21:58:50.507 回答