我想创建一个简单的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