ChatGPT解决这个技术问题 Extra ChatGPT

iOS 7 - Status bar overlaps the view

I have a ViewController which is inside a UINavigationcontroller, but the navigationBar is hidden. When I run the app on iOS 7, the status bar shows on top of my view. Is there a way to avoid this?

I don't want to write any OS specific code.

https://i.stack.imgur.com/IxX45.png

I tried setting View controller-based status bar appearance to NO, but it did not fix the issue.

I have posted my answer to show status bar like iOS 6 in iOS 7 stackoverflow.com/questions/18294872/…
You need to adjust y origin and delta value as well to handle the status bar issue This may helps you stackoverflow.com/q/18980925/1545180

P
Peter Mortensen

Xcode 5 has iOS 6/7 Deltas which is specifically made to resolve this issue. In the storyboard, I moved my views 20 pixels down to look right on iOS 7 and in order to make it iOS 6 compatible, I changed Delta y to -20.

https://i.stack.imgur.com/e4P7J.png

Since my storyboard is not using auto-layout, in order to resize the height of views properly on iOS 6 I had to set Delta height as well as Delta Y.


your answer is right but doesn't work with 4" display. Please update your answer if you can make it work for 4" display as well. Thanks in advance.
@AnkitMehta I didn't have to do anything specific for 4" iphones
worked for me. Notice that in order to see this deltas, you have to deselect 'Use Autolayout' under 'Identity and Type' for storyboard.
I found out besides setting a -20 for ∆Y, I had to also set a +20 to ∆Height
What happens when statusbar height will change? F.ex.: when user activates hot-spot, etc.... then height is 40px...
N
Nathan H

If you simply do NOT want any status bar at all, you need to update your plist with this data: To do this, in the plist, add those 2 settings:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

In iOS 7 you are expected to design your app with an overlaid transparent status bar in mind. See the new iOS 7 Weather app for example.


This is actually the only good answer since it fixes the issue at its core in the way it was meant to be done. So: upvotes needed!
It might be appropriate for some situations, but you want to be very careful hiding the status bar. Only for views that are justifiably full screen, like media players or image viewers.
@eleven59, you mean the way the autocrats at Apple intend.
Definitely like this better than changing the offset of a view controller (which feels really dirty).
hiding status bar is not a good idea... I know this is easiest way to handle iOS 7, but timing is NEEDED...
B
Bhavin Ramani

This is the default behaviour for UIViewController on iOS 7. The view will be full-screen which means the status bar will cover the top of your view.

If you have a UIViewController within a UINavigationController and the navigationBar is visible, you can have the following code in your viewDidLoad or have a background image for navigationBar do the trick.

self.edgesForExtendedLayout = UIRectEdgeNone;

If you have navigationBar hidden, then you have to adjust all the UIView elements by shifting 20 points. I dont't see any other solution. Use auto layout will help a little bit.

Here is the sample code for detecting the iOS version, if you want to backward compatibility.

NSUInteger DeviceSystemMajorVersion() {
    static NSUInteger _deviceSystemMajorVersion = -1;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        _deviceSystemMajorVersion = [[systemVersion componentsSeparatedByString:@"."][0] intValue];
    });

   return _deviceSystemMajorVersion;
}

Instead of fetching, parsing and comparing the system version, it is recommended to use if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
T
Tim Kozak

Only working solution i've made by my self.

Here is my UIViewController subclass https://github.com/comonitos/ios7_overlaping

1 Subclass from UIViewController

2 Subclass your window.rootViewController from that class.

3 Voila!

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect screen = [[UIScreen mainScreen] bounds];
        if (self.navigationController) {
            CGRect frame = self.navigationController.view.frame;
            frame.origin.y = 20;
            frame.size.height = screen.size.height - 20;
            self.navigationController.view.frame = frame;
        } else {
            if ([self respondsToSelector: @selector(containerView)]) {
                UIView *containerView = (UIView *)[self performSelector: @selector(containerView)];

                CGRect frame = containerView.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                containerView.frame = frame;
            } else {
                CGRect frame = self.view.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                self.view.frame = frame;
            }
        }
    }
}

4 Add this to make your status bar white Just right after the [self.window makeKeyAndVisible]; !!!

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

but this is not showing the time at the top... Biggest disadvantage... :(
Works great, but for step 4 you should use preferredStatusBarStyle in your view controller, as setStatusBarStyle is deprecated and it's default action is to do nothing. stackoverflow.com/a/19014724/1192732
D
Darshit Shah
-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

-(void)viewWillLayoutSubviews{

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
  {
    self.view.clipsToBounds = YES;
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = 0.0;
    if(UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        screenHeight = screenRect.size.height;
    else
        screenHeight = screenRect.size.width;
    CGRect screenFrame = CGRectMake(0, 20, self.view.frame.size.width,screenHeight-20);
    CGRect viewFrame1 = [self.view convertRect:self.view.frame toView:nil];
    if (!CGRectEqualToRect(screenFrame, viewFrame1))
    {
        self.view.frame = screenFrame;
        self.view.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    }
  }
}

Add Key in plist--- View controller-based status bar appearance : NO


change window color if require
Thanks, It solved my overlapping issue. But one issue still there - View controller-based status bar appearance : NO is to hide status bar I guess. But when I set it to YES, then its not showing status bar and when I set it to NO then it's showing status bar. So plz tell me am I wrong with concept or what?
I think because take default semi transparant color set in didFinishLaunchingWithOptions 'self.window.backgroundColor = [UIColor blueColor];' and set in plist View controller-based status bar appearance YES
Nice thanks! Also, just to point out that apple docs recommend if checking with if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) {} else {}. Cheers!
Thank you so much.Your code is so helpful for us.Please need to explain about viewWillLayoutSubviews function.
M
Mandeep Pasbola

To hide status bar in ios7 follow these simple steps :

In Xcode goto "Resources" folder and open "(app name)-Info.plist file".

check for "View controller based status bar appearance" key and set its value "NO"

check for "Status bar is initially hidden" key and set its value "YES"

If the keys are not there then you can add it by selecting "information property list" at top and click + icon


Read the question clearly, He did not ask to totally hide status bar.
@AspersionCast : He asked "Is there a way to avoid this?" and this is one of the way to avoid it.
C
Community

If you wan to hide it completely and just avoid dealing with it, this works well.

-(BOOL) prefersStatusBarHidden
{
    return YES;
}

reference https://stackoverflow.com/a/18873777/1030449


t
tipycalFlow

If using xibs, a very easy implementation is to encapsulate all subviews inside a container view with resizing flags (which you'll already be using for 3.5" and 4" compatibility) so that the view hierarchy looks something like this

https://i.stack.imgur.com/iJkfp.png

and then in viewDidLoad, do something like this:

- (void)viewDidLoad
{
  [super viewDidLoad];
  // initializations
  if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) // only for iOS 7 and above
  {
    CGRect frame = containerView.frame;
    frame.origin.y += 20;
    frame.size.height -= 20;
    containerView.frame = frame;
  }
}

This way, the nibs need not be modified for iOS 7 compatibility. If you have a background, it can be kept outside containerView and let it cover the whole screen.


T
Tony

https://i.stack.imgur.com/RsCCW.png


S
Saru

For Navigation Bar :

Writing this code :

self.navigationController.navigationBar.translucent = NO;

just did the trick for me.


R
RamaKrishna Chunduri

Vincent's answer edgesForExtendedLayout worked for me.

These macros help in determining os version making it easier

// 7.0 and above 
#define IS_DEVICE_RUNNING_IOS_7_AND_ABOVE() ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) 

// 6.0, 6.0.x, 6.1, 6.1.x
#define IS_DEVICE_RUNNING_IOS_6_OR_BELOW() ([[[UIDevice currentDevice] systemVersion] compare:@"6.2" options:NSNumericSearch] != NSOrderedDescending) 

add these macros to prefix.pch file of your project and can be accessed anywhere

if(IS_DEVICE_RUNNING_IOS_7_AND_ABOVE())
{
 //some iOS 7 stuff
 self.edgesForExtendedLayout = UIRectEdgeNone;
}

if(IS_DEVICE_RUNNING_IOS_6_OR_BELOW())
{
 // some old iOS stuff
}

for me self.edgesForExtendedLayout = UIRectEdgeNone; is not working... any reason why?
s
stema

I have posted my answer to another post with the same question with this one.

From Apple iOS7 transition Guide, https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/AppearanceCustomization.html#//apple_ref/doc/uid/TP40013174-CH15-SW1

Specifically automaticallyAdjustsScrollViewInsets=YES and set self.edgesForExtendedLayout = UIRectEdgeNone works for me when I don't want to the overlap and I have a tableviewcontroller.


A
Ali Shahid

If you want "Use Autolayout" to be enabled at any cost place the following code in viewdidload.

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
{
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.extendedLayoutIncludesOpaqueBars = NO;
        self.automaticallyAdjustsScrollViewInsets = NO;
}

J
John Pang

My status bar and navigation bar overlap after return from landscape view of YTPlayer. Here is my solution after trying @comonitos' version but not work on my iOS 8

- (void)fixNavigationBarPosition {
    if (self.navigationController) {
        CGRect frame = self.navigationController.navigationBar.frame;
        if (frame.origin.y != 20.f) {
            frame.origin.y = 20.f;
            self.navigationController.navigationBar.frame = frame;
        }
    }
}

Just call this function whenever you want to fix the position of navigation bar. I called on YTPlayerViewDelegate's playerView:didChangeToState:

- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state {
    switch (state) {
        case kYTPlayerStatePaused:
        case kYTPlayerStateEnded:
            [self fixNavigationBarPosition];
            break;
        default:
    }
}