In iOS 7 the UIStatusBar
has been designed in a way that it merges with the view like this:
(GUI designed by Tina Tavcar)
It is cool, but it will somewhat mess up your view when you have something at the top part of your view, and it becomes overlapped with the status bar.
Is there a simple solution (such as setting a property in info.plist) that can change the way it works [not overlapping] back to how it is in iOS6?
I know a more straightforward solution is to have self.view.center.x
+ 20 points for every single view controller, but changing them will screw other dimensions up (having a different self.view.center.x
can cause problem to custom segues, etc.) and suddenly it turns into a tedious job that is best to be avoided.
I'll really be glad if someone can provide me an one-liner solution for this.
P.S. I know I can hide the status bar by doing things like having
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
In didFinishLaunchingWithOptions
method, but that's a workaround, a shortcut avoiding the problem, so I don't consider that a real solution.
This question is related to
ios
objective-c
ios7
statusbar
I have achieved status bar like iOS 6 in iOS 7.
Set UIViewControllerBasedStatusBarAppearance to NO in info.plist
Pase this code in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
[application setStatusBarStyle:UIStatusBarStyleLightContent];
self.window.clipsToBounds =YES;
self.window.frame = CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height);
//Added on 19th Sep 2013
NSLog(@"%f",self.window.frame.size.height);
self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height);
}
It may push down all your views by 20 pixels.To over come that use following code in -(void)viewDidAppear:(BOOL)animated
method
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
CGRect frame=self.view.frame;
if (frame.size.height==[[NSUserDefaults standardUserDefaults] floatForKey:@"windowHeight"])
{
frame.size.height-=20;
}
self.view.frame=frame;
}
You have to set windowHeight Userdefaults value after window allocation in didFinishLauncing Method like
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[NSUserDefaults standardUserDefaults] setFloat:self.window.frame.size.height forKey:@"windowHeight"];
This may be a overwhelming problem if you use Auto layout because you can not directly manipulate frames anymore. There is a simple solution without too much work.
I ended up writing an utility method in an Utility Class and called it from all the view controllers's viewDidLayoutSubviews
Method.
+ (void)addStatusBarIfiOS7:(UIViewController *)vc
{
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
CGRect viewFrame = vc.view.frame;
if(viewFrame.origin.y == 20) {
//If the view's y origin is already 20 then don't move it down.
return;
}
viewFrame.origin.y+=20.0;
viewFrame.size.height-= 20.0;
vc.view.frame = viewFrame;
[vc.view layoutIfNeeded];
}
}
Override your viewDidLayoutSubviews
method in the view controller, where you want status bar. It will get you through the burden of Autolayout.
- (void)viewDidLayoutSubviews
{
[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
[super viewDidLayoutSubviews];
[MyUtilityClass addStatusBarIfiOS7:self];
}
The easiest way to do so is installing an older SDK to your newest Xcode.
How to install older SDK to the newest Xcode?
U can get the iOS 6.1 SDK from http://www.4shared.com/zip/NlPgsxz6/iPhoneOS61sdk.html or downloading an older Xcode and geting the SDK from its contents
Unzip and paste this folder to /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs
Restart the xcode.
Hope it helps you. It worked for me =)
If you're using Interface builder, try this:
In your xib file:
1) Select the main view, set the background color to black (or whatever color you want the status bar to be
2) Make sure the background is a self contained subview positioned as a top level child of the controller's view.
Move your background to become a direct child of the controller's view. Check the autosizing panel to be sure that you've locked all frame edges, activated both flexibility axes, and if this is a UIImageView, set the content mode to Scale to fill. Programmatically this translates to contentMode set to UIViewContentModeScaleToFill and has its auto resizing mask set to (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight).
3) Now move everything that is locked to the top - down by 20 pts and set a iOS 6/7 delta Y to -20.
All top level children that are locked to the top frame in the autosizing panel need to be moved down by 20pts and have their iOS 6/7 delta Y set to -20. (Cmd select all of those, and click down arrow 20 times - is there a better way anyone?)
4) Adjust the iOS 6/7 delta height of all of the above items that had a flexible height. Any of the items that were locked to the frame top and bottom and had flexible height enabled in the autosizing panel must also have their iOS 6/7 delta height set to 20. That includes the background view mentioned above. This may seem anti-intuitive, but due to the order in which these are applied, it is necessary. The frame height is set first (based on device), then the deltas are applied, and finally the autosizing masks are applied based upon the offset positions of all of the child frames - think it through for a bit, it will make sense.
5) Finally, items that were locked to the bottom frame but not the top frame need no deltas at all.
That will give you the identical status bar in iOS7 and iOS6.
On the other hand, if you want iOS7 styling while maintaining iOS6 compatibility, then set the delta Y / delta height values to 0 for the background view.
To see more iOS7 migration info read the full post: http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html
I found here is the best alternatives and solution for this navigation bar issue in iOS7!!
http://www.appcoda.com/customize-navigation-status-bar-ios-7/
I hope it will clear our all queries and worries.
Apple released Technical Q&A QA1797: Preventing the Status Bar from Covering Your Views. It works fine for the iOS 6 and iOS 7 versions.
I am late for this Answer, but i just want to share what i did, which is basically the easiest solution
First of all-> Go to your info.plist
File and add Status Bar Style->Transparent Black Style(Alpha of 0.5)
Now ,here it Goes:-
Add this code in your AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Whatever your code goes here
if(kDeviceiPad){
//adding status bar for IOS7 ipad
if (IS_IOS7) {
UIView *addStatusBar = [[UIView alloc] init];
addStatusBar.frame = CGRectMake(0, 0, 1024, 20);
addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //change this to match your navigation bar
[self.window.rootViewController.view addSubview:addStatusBar];
}
}
else{
//adding status bar for IOS7 iphone
if (IS_IOS7) {
UIView *addStatusBar = [[UIView alloc] init];
addStatusBar.frame = CGRectMake(0, 0, 320, 20);
addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //You can give your own color pattern
[self.window.rootViewController.view addSubview:addStatusBar];
}
return YES;
}
Steps For Hide the status bar in iOS 7:
1.Go to your application info.plist file.
2.And Set, View controller-based status bar appearance : Boolean NO
Hope i solved the status bar issue.....
My solution was to add a UIView
with height of 20 points on top of the window when on iOS 7.
Then I created a method in my AppDelegate class to show/hide the "solid" status bar background. In application:didFinishLaunchingWithOptions:
:
// ...
// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];
// ...
return YES;
Then I created a method to fade in/out the black status bar background:
- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
[UIView animateWithDuration:0.3f animations:^{
if(solidStatusBar)
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
self.statusBarBackground.alpha = 1.0f;
}
else
{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
self.statusBarBackground.alpha = 0.0f;
}
}];
}
All I have to do now is call is [appDelegate showSolidStatusBar:YES]
when needed.
As using presentViewController:animated:completion:
messed-up the window.rootViewController.view
, I had to find a different approach to this issue. I finally got it to work with modals and rotations by subclassing the UIView of my rootViewController.
.h
@interface RootView : UIView
@end
.m
@implementation RootView
-(void)setFrame:(CGRect)frame
{
if (self.superview && self.superview != self.window)
{
frame = self.superview.bounds;
frame.origin.y += 20.f;
frame.size.height -= 20.f;
}
else
{
frame = [UIScreen mainScreen].applicationFrame;
}
[super setFrame:frame];
}
- (void)layoutSubviews
{
self.frame = self.frame;
[super layoutSubviews];
}
@end
You now have a strong workaround for iOS7 animations.
This might be too late to share, but I have something to contribute which might help someone, I was trying to sub-class the UINavigationBar and wanted to make it look like ios 6 with black status bar and status bar text in white.
Here is what I found working for that
self.navigationController?.navigationBar.clipsToBounds = true
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barStyle = .Black
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
It made my status bar background black, status bar text white and navigation bar's color white.
iOS 9.3, XCode 7.3.1
I used this in all my view controllers, it's simple. Add this lines in all your viewDidLoad methods:
- (void)viewDidLoad{
//add this 2 lines:
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
[super viewDidLoad];
}
Here another approach for projects that make extensive use of the Storyboard:
GOAL:
Goal of this approach is to recreate the same status bar style in iOS7 as there was in iOS6 (see question title "iOS 7 Status Bar Back to iOS 6 style?").
SUMMARY:
To achieve this we use the Storyboard as much as possible by shifting UI elements that are overlapped by the status bar (under iOS 7) downwards, whilst using deltas to revert the downwards layout change for iOS 6.1 or earlier. The resulting extra space in iOS 7 is then occupied by a UIView with the backgroundColor set to a color of our choosing. The latter can be created in code or using the Storyboard (see ALTERNATIVES below)
ASSUMPTIONS:
To get the desired result when following the steps below, it is assumed that View controller-based status bar appearance
is set to NO and that your Status bar style
is either set to "Transparent black style (alpha of 0.5)" or "Opaque black style". Both settings can be found/or added under "Info" in your project settings.
STEPS:
Add a subview to the UIWindow to serve as your status bar background. To achieve this, add the following to your AppDelegate's application: didFinishLaunchingWithOptions:
after makeKeyAndVisible
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20)];
statusBarBackgroundView.backgroundColor = [UIColor blackColor];
[yourAppsUIWindow addSubview:statusBarBackgroundView];
}
Since you programmatically added a background for iOS 7 ONLY, you will have to adjust the layout of your UI elements that are overlapped by the status bar accordingly whilst preserving their layout for iOS6. To achieve this, do the following:
Use Autolayout
is unchecked for your Storyboard (this is because otherwise "iOS 6/7 Deltas" is not shown in the Size Inspector). To do this:
ALTERNATIVES:
To add even less code in storyboard-heavy projects and to have the statusbar background autorotate, instead of programmatically adding a background for your statusbar, you could add a colored view to each view controller that sits at the very top of said viewcontroller's main view. You would then change the height delta of this new view to the same negative amount as your view's height (to make it disappear under iOS 6).
The downside of this alternative (although maybe negligible considering the autorotate compatibility) is the fact that this extra view is not immediately visible if you are viewing your Storyboard for iOS 6. You would only know that it's there if you had a look at the "Document Outline" of the Storyboard.
You can hide the status bar all together. So your app will be full-screen. I think that's the best you will get.
UIStatusBarStyleNone
or set in the target settings.
Updates on 19th Sep 2013:
fixed scaling bugs by adding
self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
corrected typos in the
NSNotificationCenter
statement
Updates on 12th Sep 2013:
corrected
UIViewControllerBasedStatusBarAppearance
toNO
added a solution for apps with screen rotation
added an approach to change the background color of the status bar.
There is, apparently, no way to revert the iOS7 status bar back to how it works in iOS6.
However, we can always write some codes and turn the status bar into iOS6-like, and this is the shortest way I can come up with:
Set UIViewControllerBasedStatusBarAppearance
to NO
in info.plist
(To opt out of having view controllers adjust the status bar style so that we can set the status bar style by using the UIApplicationstatusBarStyle method.)
In AppDelegate's application:didFinishLaunchingWithOptions
, call
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
[application setStatusBarStyle:UIStatusBarStyleLightContent];
self.window.clipsToBounds =YES;
self.window.frame = CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
//Added on 19th Sep 2013
self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
}
return YES;
in order to:
Check if it's iOS 7.
Set status bar's content to be white, as opposed to UIStatusBarStyleDefault.
Avoid subviews whose frames extend beyond the visible bounds from showing up (for views animating into the main view from top).
Create the illusion that the status bar takes up space like how it is in iOS 6 by shifting and resizing the app's window frame.
use NSNotificationCenter to detect orientation changes by adding
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
in if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
and create a new method in AppDelegate:
- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
int a = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
int w = [[UIScreen mainScreen] bounds].size.width;
int h = [[UIScreen mainScreen] bounds].size.height;
switch(a){
case 4:
self.window.frame = CGRectMake(0,20,w,h);
break;
case 3:
self.window.frame = CGRectMake(-20,0,w-20,h+20);
break;
case 2:
self.window.frame = CGRectMake(0,-20,w,h);
break;
case 1:
self.window.frame = CGRectMake(20,0,w-20,h+20);
}
}
So that when orientation changes, it will trigger a switch statement to detect app's screen orientation (Portrait, Upside Down, Landscape Left, or Landscape Right) and change the app's window frame respectively to create the iOS 6 status bar illusion.
Add
@property (retain, nonatomic) UIWindow *background;
in AppDelegate.h
to make background
a property in your class and prevent ARC from deallocating it. (You don't have to do it if you are not using ARC.)
After that you just need to create the UIWindow in if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
:
background = [[UIWindow alloc] initWithFrame: CGRectMake(0, 0, self.window.frame.size.width, 20)];
background.backgroundColor =[UIColor redColor];
[background setHidden:NO];
Don't forget to @synthesize background;
after @implementation AppDelegate
!
My very simple solution (assuming you have only vertical orientation supported) is to redefine application window bounds for iOS versions below 7, in App delegate didFinishLaunchingWithOptions method:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if ([HMService getIOSVersion] < 7) {
// handling statusBar (iOS6) by leaving top 20px for statusbar.
screenBounds.origin.y = 20;
self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
else {
self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
Try this simple method....
Step 1:To change in single viewController
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];
Step 2: To change in whole application
info.plist
----> Status Bar Style
--->UIStatusBarStyle to UIStatusBarStyleBlackOpaque
Step 3: Also add this in each viewWillAppear
to adjust statusbar
height for iOS7
[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
if ([[UIDevice currentDevice].systemVersion floatValue] >= 7) {
CGRect frame = [UIScreen mainScreen].bounds;
frame.origin.y+=20.0;
frame.size.height-= 20.0;
self.view.frame = frame;
[self.view layoutIfNeeded];
}
I have viewed many many many many and many tutorials to fix this darn problem. But none of them works! Here is my solution, and it works for me:
if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f ) {
float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
for( UIView *v in [self.view subviews] ) {
CGRect rect = v.frame;
rect.origin.y += statusBarHeight;
v.frame = rect;
}
}
The logic is simple. I shift all children views on the self.view with 20 pixels. That's all. Then, the screenshot will display just like as iOS 6 did. I hate the iOS7 status bar! ~"~
A small alternative to Archy Holt's answer, a bit more simple:
a. Set UIViewControllerBasedStatusBarAppearance
to NO
in info.plist
b. In AppDelegate
's application:didFinishLaunchingWithOptions:
, call:
if ([[UIDevice currentDevice].systemVersion floatValue] < 7)
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
else
{
// handling statusBar (iOS7)
application.statusBarStyle = UIStatusBarStyleLightContent;
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
self.window.clipsToBounds = YES;
// handling screen rotations for statusBar (iOS7)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}
And add the method:
- (void)applicationDidChangeStatusBarOrientationNotification:(NSNotification *)notification
{
// handling statusBar (iOS7)
self.window.frame = [UIScreen mainScreen].applicationFrame;
}
You can also consider subclassing UIWindow
to handle UIApplicationDidChangeStatusBarOrientationNotification
itself.
In order to continue working with setStatusBarHidden: I use this category:
@interface UIApplication (StatusBar)
-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden;
@end
@implementation UIApplication (StatusBar)
-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden{
if (!IOS7) {
[self setStatusBarHidden:statusBarHidden];
return;
}
if ([self isStatusBarHidden] == statusBarHidden) {
return;
}
[self setStatusBarHidden:statusBarHidden];
[self keyWindow].clipsToBounds = YES;
CGFloat offset = statusBarHidden ? 0 : 20;
[self keyWindow].frame = CGRectMake(0,offset,[self keyWindow].frame.size.width,[self keyWindow].frame.size.height-offset);
[self keyWindow].bounds = CGRectMake(0, offset, [self keyWindow].frame.size.width,[self keyWindow].frame.size.height);
}
@end
UPDATE(NEW SOLUTION)
This update is the best solution of iOS 7 navigation bar problem.You can set navigation bar color example: FakeNavBar.backgroundColor = [UIColor redColor];
Note : If you use default Navigation Controller please use old solution.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0)
{
UIView *FakeNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
FakeNavBar.backgroundColor = [UIColor whiteColor];
float navBarHeight = 20.0;
for (UIView *subView in self.window.subviews) {
if ([subView isKindOfClass:[UIScrollView class]]) {
subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height - navBarHeight);
} else {
subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height);
}
}
[self.window addSubview:FakeNavBar];
}
return YES;
}
OLD SOLUTION - IF you use previous code please ignore following Code and Image
This is old version of iOS 7 navigation bar solution.
I solved the problem with the following code. This is for adding a status bar.
didFinishLaunchingWithOptions
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
UIView *addStatusBar = [[UIView alloc] init];
addStatusBar.frame = CGRectMake(0, 0, 320, 20);
addStatusBar.backgroundColor = [UIColor colorWithRed:0.973 green:0.973 blue:0.973 alpha:1]; //change this to match your navigation bar
[self.window.rootViewController.view addSubview:addStatusBar];
}
And for Interface Builder this is for when you open with iOS 6; it is starting at 0 pixels.
SOLUTION :
Set it in your viewcontroller or in rootviewcontroller by overriding the method :
-(BOOL) prefersStatusBarHidden
{
return YES;
}
There is an option in the Interface Builder which calls the iOS 6/7 Delta property which aim to solve the offset problem.
Take a look at it in Stack Overflow question Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?.
If you don't want your view controllers to be overlapped by the status bar (and navigation bars), uncheck the "Extend Edges Under Top Bars" box in Interface Builder in Xcode 5.
Source: Stackoverflow.com