2

我想创建一个简单的mobilesubstrate 调整,隐藏和显示状态栏图标,如电池或运营商或 wifi 信号指示器。我看过libstatusbar项目,但我不知道如何隐藏 iOS 的图标。有没有其他方法可以在不使用这个库的情况下做到这一点?我只想隐藏和显示默认图标

4

4 回答 4

4

无法使用公共 API。您只能隐藏整个状态栏,而不仅仅是它的某些元素。

对于越狱,请看:

https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIStatusBarItem.h

特别是,请查看以下方法:

+ (BOOL)itemType:(int)arg1 idiom:(int)arg2 appearsInRegion:(int)arg3;
+ (BOOL)itemType:(int)arg1 idiom:(int)arg2 canBeEnabledForData:(id)arg3 style:(id)arg4;

无论项目是否应该出现,都会参考这些方法。返回NO此处禁用项目。

于 2014-06-12T16:31:38.440 回答
2

这是我在调整中使用的:

int itemToHide = 0;
[[objc_getClass("SBStatusBarStateAggregator") sharedInstance] beginCoalescentBlock];
[[objc_getClass("SBStatusBarStateAggregator") sharedInstance] _setItem:itemToHide enabled:NO];
[[objc_getClass("SBStatusBarStateAggregator") sharedInstance] endCoalescentBlock];

唯一的问题 - iOS 对状态栏项目使用整数值,并且它们在不同的 iOS 版本上有所不同。您可以测试每个 iOS 版本并为每个版本存储值,但我找到了更好的方法。

我钩SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2法。然后我调用其中一种SBStatusBarStateAggregator -(void)_update****方法。例如,假设我要查找位置图标索引。我叫SBStatusBarStateAggregator -(void)_updateLocationItem方法。然后它将调用 hookedSBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2我将存储索引的位置。

我也钩SBStatusBarStateAggregator -(void)_notifyItemChanged:(int)arg。此方法作为调用的一部分SBStatusBarStateAggregator -(void)_update****调用。在确定状态栏图标索引时,我只是通过返回而不调用原始实现来忽略对它的调用。

而且,如果您想永久隐藏某些图标,您仍然需要挂钩SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2SBStatusBarStateAggregator -(void)_notifyItemChanged:(int)arg忽略任何 iOS 显示隐藏图标的尝试。例如,信号电平和数据/时间在每次更新时都会重新启用。

这就是 iOS 7 的全部内容。在 iOS 5-6 上,API 有所不同,但我使用几乎相同的方法。隐藏状态栏项目

int itemToHide = 0;
[[objc_getClass("SBStatusBarDataManager") sharedDataManager] setStatusBarItem:itemToHide enabled:NO];

我挂钩SBStatusBarDataManager -(void)updateStatusBarItem:(int)item以确定图标索引,然后SBStatusBarDataManager -(void)_locationStatusChange在位置图标的情况下调用。

于 2014-06-13T00:06:51.117 回答
1

好的。这是解决方案。
在您的 plist 文件中添加行:

查看基于控制器的状态栏外观:否

使用以下内容在 UINavigationBar 上创建一个类别:

#import "UINavigationBar+StatusBar.h"
#进口

@implementation UINavigationBar(状态栏)

+(空)负载
{
    [self swizzleOriginalSelectorWithName:@"layoutSubviews" toSelectorWithName:@"my_layoutSubviews"];
}

- (void)my_layoutSubviews
{
    [自我 my_layoutSubviews];
    [self setFrame:CGRectMake(0, 0, self.frame.size.width, 64)];
}

+ (void)swizzleOriginalSelectorWithName:(NSString *)origName toSelectorWithName:(NSString *)swizzleName
{
    方法 origMethod = class_getInstanceMethod([self class], NSSelectorFromString(origName));
    Method newMethod = class_getInstanceMethod([self class], NSSelectorFromString(swizzleName));
    method_exchangeImplementations(origMethod, newMethod);
}

@结尾

这将增加 20pt 的导航栏。

然后,为状态栏制作自定义视图。例如

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [自己制作CustomSatusBar];
    // 应用程序启动后自定义的覆盖点。
    返回是;
}

- (void)makeCustomSatusBar
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];

    UIColor *statusBarColor = [UIColor blackColor];

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.frame.size.width, 20)];
    view.layer.zPosition = INT_MAX;
    view.backgroundColor = [UIColor clearColor];

    // 制作时间标签
    NSDateFormatter *formatter = [NSDateFormatter new];
    formatter.dateFormat = @"HH:mm";
    UILabel *timeLabel = [UILabel 新];
    timeLabel.text = [formatter stringFromDate:[NSDate date]];
    timeLabel.textColor = statusBarColor;
    timeLabel.font = [UIFont systemFontOfSize:12];
    [timeLabel sizeToFit];
    timeLabel.center = CGPointMake(view.frame.size.width/2, view.frame.size.height/2);
    [查看 addSubview:timeLabel];
    //

    // 制作您需要的其他指标...
    //...

    [self.window addSubview:view];
}

你会有这样的东西:

在此处输入图像描述

请注意,您每次都需要更新自定义视图的值(即时间标签、电池等),因此最好为您的状态栏创建一个单独的类,并制作一个 1 秒的无限计时器勾选并在计时器的操作中进行更新。

于 2014-06-12T17:20:30.157 回答
0

可能你只需要这个?

[[UIApplication sharedApplication] setStatusBarHidden:YES]

如果您只想在 20pt 高度之上的空视图,然后将其添加到 UIWindow,然后将 UIWindow 的子视图向下移动 20 pt

于 2014-06-12T16:32:00.787 回答