62

是否可以在尺寸(320 x 20)的状态栏上添加 UIView?我不想隐藏状态栏,我只想将它添加到状态栏的顶部。

4

5 回答 5

87

您可以通过在现有状态栏上方创建自己的窗口来轻松完成此操作。

UIWindow只需使用以下覆盖创建一个简单的子类initWithFrame:

@interface ACStatusBarOverlayWindow : UIWindow {
}
@end

@implementation ACStatusBarOverlayWindow
- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        // Place the window on the correct level and position
        self.windowLevel = UIWindowLevelStatusBar+1.0f;
        self.frame = [[UIApplication sharedApplication] statusBarFrame];

        // Create an image view with an image to make it look like a status bar.
        UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.frame];
        backgroundImageView.image = [UIImage imageNamed:@"statusBarBackground.png"];
        [self addSubview:backgroundImageView];
        [backgroundImageView release];

        // TODO: Insert subviews (labels, imageViews, etc...)
    }
    return self;
}
@end

例如,您现在可以在应用程序的视图控制器中创建新类的实例并使其可见。

overlayWindow = [[ACStatusBarOverlayWindow alloc] initWithFrame:CGRectZero];
overlayWindow.hidden = NO;

请注意使用- (void)makeKeyAndVisible或类似方法弄乱窗口键状态。如果您使主窗口(UIWindow在您的应用程序委托中)处于松散键状态,则在点击状态栏等时会遇到滚动滚动视图到顶部的问题。

于 2010-05-14T12:22:59.760 回答
58

我写了一个模仿 Reeders 状态栏覆盖的静态库,你可以在这里找到它:https ://github.com/myell0w/MTStatusBarOverlay

MTStatusBarOverlay MTStatusBarOverlay

它目前支持 iPhone 和 iPad、默认和不透明的黑色状态栏样式、旋转、3 种不同的动画模式、历史跟踪和更多好东西!

随意使用它或向我发送请求请求以增强它!

于 2010-12-10T23:51:58.997 回答
4

所有答案看起来都有效,但在 iOS6.0 中我遇到了下一个问题:

1/ 旋转看起来很糟糕

2/ 窗口(状态栏是一种窗口)需要 rootViewController

我正在使用myell0w的答案,但旋转效果不佳。我刚刚删除了一个额外的窗口并使用 AppDelegate 中的 UIWindow 来实现状态栏。可能这个解决方案只适用于一个 UIViewController-app...

我通过下一种方式实现:

1/ 在 ApplicationDelegate 中:

self.window.windowLevel = UIWindowLevelStatusBar + 1;
self.window.backgroundColor = [UIColor clearColor];
self.window.rootViewController = _journalController;

2/ 创建自定义 UIView 并在内部实现您需要的所有内容:例如可触摸状态栏:

@interface LoadingStatusBar : UIControl 

并轻松创建并添加到您的控制器视图:

_loadingBar = [[LoadingStatusBar alloc] initWithFrame:topFrame];
[self addSubview:_loadingBar];

3/ 添加控制器视图时的一些魔法(在 initWithFrame 中:)

    CGRect mainFrame = self.bounds;
    mainFrame.origin.y = 20;
    self.bounds = mainFrame;

您的控制器视图将有 2 个视图 - 内容视图和状态栏视图。您可以显示状态栏,也可以在需要时隐藏它。内容视图的框架将是:

_contentView.frame = CGRectMake(0, 20, self.bounds.size.width, self.bounds.size.height);

4/这里还有最后一个魔法:)为了检测我使用过的不可触摸区域的触摸:

-(id)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (point.y < 20) return _loadingBar;
    return [super hitTest:point withEvent:event];
}

目前它在 iPad/iPhone 和所有 iOS 4 到 6 上运行良好。

于 2012-11-20T14:40:18.860 回答
3

只是为了驳回“你不能做这个评论”......

我不知道怎么做,但我知道这是可行的。名为 Reeder 的 Feed 阅读器应用程序可以做到这一点。

从截图可以看出,Reeder 在屏幕右上角放了一个小点。当你点击它时。该栏将填满整个状态栏,直到您再次点击它以使其变小。

屏幕右上角的小图标 替代文字

于 2010-05-14T11:58:48.580 回答
1

首先,非常感谢@Martin Alléus 提供了此实现的代码。

我只是发布我遇到的问题和我使用的解决方案,因为我相信其他人可能会遇到同样的问题。

如果应用程序在通话到位时启动,状态栏高度将为 40 像素,这意味着自定义状态栏将使用该高度进行初始化。但是如果通话结束时你还在应用程序中,状态栏高度仍将保持 40 像素,看起来会很奇怪。

所以解决方案很简单:我已经使用通知中心订阅了应用的状态栏框架更改委托,并调整了框架:

- (void)application:(UIApplication *)application didChangeStatusBarFrame:(CGRect)oldStatusBarFrame {
    //an in call toggle was done    
    //fire notification
    [[NSNotificationCenter defaultCenter] postNotificationName:kStatusBarChangedNotification object:[NSValue valueWithCGRect:oldStatusBarFrame]];
}

在 ACStatusBarOverlayWindow 我们订阅通知:

-(id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame]))
    {
        // Place the window on the correct level & position
        self.windowLevel = UIWindowLevelStatusBar + 1.0f;
        self.frame = [UIApplication sharedApplication].statusBarFrame;
        self.backgroundColor = [UIColor blackColor];

        //add notification observer for in call status bar toggling
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarChanged:) name:kStatusBarChangedNotification object:nil];
    }
    return self;
}

以及我们调整框架的代码:

- (void)statusBarChanged:(NSNotification*)notification {
    //adjust frame...    
    self.frame = [UIApplication sharedApplication].statusBarFrame;
    //you should adjust also the other controls you added here
}

kStatusBarChangedNotification只是我用来方便引用的常量,您可以简单地用字符串替换它,或者全局声明该常量。

于 2012-10-23T20:09:45.480 回答