Moving status bar in iOS 7
Solution 1
The gist of it is to use this method introduced in iOS 7:
https://developer.apple.com/documentation/uikit/uiscreen/1617814-snapshotview:
With that you get a UIView containing a screenshot that includes the status bar. Once you have that, it's just a matter of hiding your current view then pushing the screenshot view around.
I posted a proof of concept here: https://github.com/simonholroyd/StatusBarTest
NOTE I haven't submitted code that does this through the Apple review process, but this is not a private API method.
Solution 2
So, after the initial push by Mr. Simon Holroyd and some searching, I've found the solution of how to achieve this "effect" functionality. This is the code:
statusbarView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
EDIT: mister pcholberg correctly pointed out that the former code did not work on the actual device, only on the iOS Simulator, so I've edited it by his recommendation
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
UIView *screenShot = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
[statusbarView addSubview:screenShot];
[statusbarView setClipsToBounds:YES];
[self.view addSubview:statusbarView];
[self setPrefersStatusBarHidden:YES];
[self prefersStatusBarHidden];
[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
}
...
- (BOOL)prefersStatusBarHidden
{
return prefersStatusBarHidden;
}
...
So the first part creates context, uses the method Simon mentioned, draws the view with the statusbar, and saves that as an UIImage
The second part adds the snapshot UIView
to my viewController's UIView
And the third part sets my bool for statusbar to YES (for easier use in the method above), and calls methods to redraw it
This then sets the UIView as not-functional statusbar at its place and hides the original one, so there is no double-rendering. Then I can use this view in my [UIView animateWithDuration...
method
And when I return, I use this code in the completion handler of the animation block:
[statusbarView removeFromSuperview];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
[self setPrefersStatusBarHidden:NO];
[self prefersStatusBarHidden];
[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
}
And voilá! This works as the described effect in my question.
Hope this helps somebody!
Solution 3
I use this method to move statuebar with slider view,in a application there are two window,one normal window,other statuBarWindow,i get statuBarView which superView is statuBarWindows ,and move it with slider view.
- (UIView *)statuBarView
{
NSString *key = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned char []){0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x61, 0x72} length:9] encoding:NSASCIIStringEncoding];
id object = [UIApplication sharedApplication];
UIView *statusBar = nil;
if ([object respondsToSelector:NSSelectorFromString(key)]) {
statusBar = [object valueForKey:key];
}
return statusBar;
}
Solution 4
I just created BSPanViewController which makes it extremely easy to achieve this effect. The control and instructions on how to use it can be found on GitHub.
The implementation is the same as the one explained by Simon Holroyd.
Gyfis
Chief Technology Officer at Better Stack. We're working on Better Uptime and Logtail. Ruby, Swift, Rust, Kotlin, CoffeeScript, Objective-c, JavaScript, Python is, and some others as well.
Updated on June 07, 2022Comments
-
Gyfis about 2 years
The problem I'm facing is this:
I want to implement an iOS 7 app with nice design and left/right menu, which appears after the main view animate itself to the right/left. I'm doing this with
[UIView animateWithDuration...]
code, but that's not really important. What I want to achieve is the same effect the Mailbox iOS 7 app has: to move the status bar away (to the right/left) with the main viewImage for better explanation:
What I only found is this article about the issue, with some working code using Private APIs, which I'd like not to use, since I want my app to be accepted on the App Store.
I'd like to achieve the same effect ('legally'). Does anybody knows how to?
Thanks!
-
Gyfis almost 11 yearsThis looks interesting, I'll look into it and report my findings!
-
Simon Holroyd almost 11 yearsSomething else to note if you move further with this feature: the Mailbox app has a bug where when you multitask, the screenshot it displays does not suppress the status bar. So if you exit the app with left menu open, then multitask, you'll see duplicate status bars in the multitasking view.
-
Gyfis almost 11 yearsThat's actually pretty good to know! They are not gods :) Thank you!
-
Gyfis almost 11 yearsHey, I'm just trying to write the code, but now I realized that this method just takes a screenshot of the screen! I was asking rather for a functional status bar moved than for a screenshot, although it's a nice method
-
Gyfis almost 11 yearsAlthough, as it seems, the Mailbox app does it in the same way, since the status bar does not change when moved away from the screen. The only thing that I'm thinking about now is 'Busted!'
-
Simon Holroyd almost 11 yearsYou asked how to achieve the same effect! It is just that, an effect.
-
Gyfis almost 11 yearsYes, of course you are right :) I've already accomplished the task (the effect), so I'll probably post something about it tonight here
-
pcholberg over 10 yearsDo not render snapshotView ([[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]) into image, snapshot will appear without text on statusbar on real device. Just add this shanpshot as subview.
-
Gyfis over 10 yearsYou are absolutely right! This somehow works on simulator, however does not on an actual device. But I was not able to add the snapshot as subview and move it afterwards, since it seemed it changes after some time...
-
Eric G over 10 yearsIf you got away with using a private API, it's an anomaly. There is great risk in breaking the rules, and I wouldn't advise people to try.
-
MusiGenesis over 10 yearsWhat is the purpose of
[self prefersStatusBarHidden];
in your code, since you're doing nothing with the return value? And why do you have to do[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
instead of just[self setNeedsStatusBarAppearanceUpdate]
? If your code does not work without those lines, I would be reluctant to use it in an app as it would be likely to suddenly stop working with a new iOS release. -
Gyfis over 10 yearsI've override the method prefersStatusBarHidden, which now returns a boolean - prefersStatusBarHidden (now that I see it, it's rather strange that I named them the same way!). About the selector - I'm not really sure, it's possibly some reference to a lot of tweaking and changing little bits so the whole effect would work.
-
Pavan over 10 years+1 That is Super cool @SimonHolroyd! I love the way you're using the screenshot to then use that as the view whilst hiding the actual status bar ;) hehe quite nifty! Man I wish to see other cool projects like this, if only there was a place where you could quickly see all these kind of nifty tricks for iOS development! If anyone knows of something cool like this related to anything, please do tag me and let me know! cheers!
-
Cypher over 10 yearsThis isn't how mailbox does it. Although I'm not sure how they do, you can see that their status bar notifications will finish animating even while in the 'slide-open' position. (Press the slide button immediately after you first open the app and you'll see this)
-
Cypher over 10 yearsThis is pretty interesting.. is this considered a use of apples private API? Also, why do you use dataWithBytes instead of just @"statusBar" which is what that turns into.. is that to avoid detection in some way? (seems like they would check for this simple work around..)