How to hide statusbar icons in iOS

2019-07-20 20:14发布

I want to create a simple mobilesubstrate tweak that hides and shows status bar icons like battery or Carrier or wifi signal indecator. I've seen libstatusbar project but i can't find out how to hide iOS's icons. Is there any other way to do this without the use of this library? I just want to hide and show the default icons

4条回答
走好不送
2楼-- · 2019-07-20 20:21

Ok. Here is solution.
In your plist file add row:

View controller-based status bar appearance  :  NO 

Make a category on UINavigationBar with this content:

#import "UINavigationBar+StatusBar.h"
#import 

@implementation UINavigationBar (StatusBar)

+ (void)load
{
    [self swizzleOriginalSelectorWithName:@"layoutSubviews" toSelectorWithName:@"my_layoutSubviews"];
}

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

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

@end

This will increase navigation bar for 20pt.

Then, make your custom view for status bar. e.g.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self makeCustomSatusBar];
    // Override point for customization after application launch.
    return YES;
}

- (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];

    // Making time label
    NSDateFormatter *formatter = [NSDateFormatter new];
    formatter.dateFormat = @"HH:mm";
    UILabel *timeLabel = [UILabel new];
    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);
    [view addSubview:timeLabel];
    //

    // make other indicators you need...
    //...

    [self.window addSubview:view];
}

And you will have something like this:

enter image description here

Note, that you need to update values of your custom view every time (i.e. time label, battery, etc..) , so it would be better to make a separate class for your status bar, and make a infinite timer with 1 sec of tick and do your updates in timer's action.

查看更多
可以哭但决不认输i
3楼-- · 2019-07-20 20:28

may be you just need this?

[[UIApplication sharedApplication] setStatusBarHidden:YES]

And if you want just empty view on top of 20pt height, then make that and add to UIWindow, and shift down subview of UIWindow for 20 pt

查看更多
贼婆χ
4楼-- · 2019-07-20 20:29

Not possible using public API. You can only hide the entire status bar, not only certain elements of it.

For jailbreak, take a look at:

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

In particularly, look at the following methods:

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

These methods are consulted whether iterms should appear or not. Return NO here to disable items.

查看更多
Fickle 薄情
5楼-- · 2019-07-20 20:48

Here is what I use in my tweak:

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

Only problem - iOS uses integer values for status bar items and they're different on different iOS versions. You could test every iOS version and store values for each one of them but I found a better way.

I hook SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2 method. Then I call one of the SBStatusBarStateAggregator -(void)_update**** methods. For example, let's say I want to find location icon index. I call SBStatusBarStateAggregator -(void)_updateLocationItem method. It then will call hooked SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2 where I will store the index.

I also hook SBStatusBarStateAggregator -(void)_notifyItemChanged:(int)arg. This method is called as part of SBStatusBarStateAggregator -(void)_update**** call. When determing status bar icon index I simply ignore calls to it by returning without calling original implementation.

And if you want to permanently hide some of the icons you still need to hook SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2 and SBStatusBarStateAggregator -(void)_notifyItemChanged:(int)arg in order to ignore any iOS attempts to show hidden icons. For example, signal level and data/time are reanabled every time they're updated.

That's all for iOS 7. On iOS 5-6 API is different but I use pretty much the same approach. To hide status bar item

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

I hook SBStatusBarDataManager -(void)updateStatusBarItem:(int)item to determine icon index and then call SBStatusBarDataManager -(void)_locationStatusChange in case of location icon.

查看更多
登录 后发表回答