我想创建一个简单的mobilesubstrate 调整,隐藏和显示状态栏图标,如电池或运营商或 wifi 信号指示器。我看过libstatusbar项目,但我不知道如何隐藏 iOS 的图标。有没有其他方法可以在不使用这个库的情况下做到这一点?我只想隐藏和显示默认图标
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此处禁用项目。
这是我在调整中使用的:
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)arg2并SBStatusBarStateAggregator -(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在位置图标的情况下调用。
好的。这是解决方案。
在您的 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 秒的无限计时器勾选并在计时器的操作中进行更新。
可能你只需要这个?
[[UIApplication sharedApplication] setStatusBarHidden:YES]
如果您只想在 20pt 高度之上的空视图,然后将其添加到 UIWindow,然后将 UIWindow 的子视图向下移动 20 pt