Reputation: 1174
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 view
Image 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!
Upvotes: 36
Views: 14738
Reputation: 934
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.
Upvotes: 48
Reputation: 225
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;
}
Upvotes: 7
Reputation: 1174
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!
Upvotes: 7
Reputation: 8042
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.
Upvotes: 3
Reputation: 1875
In my experience, App Store reviewers generally don't care about private API's use, especially this simple and harmless. For the task you can get a pointer to application's status bar view through several methods, which you can find in iOS complete headers like https://github.com/nst/iOS-Runtime-Headers
Upvotes: -3