StuartM
StuartM

Reputation: 6823

UINavigationBar/Status Bar issue in IOS7

Final EDIT

(Rather than having an overly long question with edits making a final edit for clarification, please see other edits if needed).

Controller Setup

I have an application that is setup as follows:

InitialViewController (subclass of ECSlidingViewController)

Main Navigation Controller (subclass of UINavigationController)

Main Home View Controller (subclass of UIViewController)


In the viewDidLoad of the initialViewController I load the main navigation controller in with the Home View Controller as its root.

self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MainNavVC"];

The Issue

On the first load of the application the status bar and navigation bar are seperated. enter image description here

This is the desired effect.

However, I then load a modal view controller and close it, using the standard methods:

[self performSegueWithIdentifier:@"LoadSelectOpponentVC" sender:self];

Then close with:

[self dismissViewControllerAnimated:YES completion:nil];

This in turn causes the main navigation controller (holding the home view controller) to display the status bar incorrectly and overlapping:

enter image description here

Testing

  1. The plist setting is set to YES - View controller-based status bar appearance
  2. I have tried setting the edgesForExtendedLayout to the relevant none, but no change.

Logging

I have tried to log out some frames to see where the issue occurs:

On first Load:

Main Nav VC - View Frame - {{0, 0}, {320, 480}}

Main Nav VC - Nav Bar Frame - {{0, 0}, {320, 44}}

Initial VC - View Frame - {{0, 0}, {320, 480}}

Home VC - View Frame - {{0, 0}, {320, 480}} -- viewDidLoad Home VC

Home VC - View Frame - {{0, 64}, {320, 416}} -- viewWillAppear Home VC

--- After Modal is opened/closed ----

Home VC - View Frame - {{0, 64}, {320, 416}} -- viewWillAppear Home VC

Main Nav VC - View Frame - {{0, 0}, {320, 480}} -- viewWillAppear Main Nav

Main Nav VC - Nav Bar Frame - {{0, 20}, {320, 44}} -- viewWillAppear Main Nav

Home VC - View Frame - {{0, 44}, {320, 436}} -- viewDidAppear Home VC

Upvotes: 48

Views: 64409

Answers (14)

Nicolas Buquet
Nicolas Buquet

Reputation: 3955

Did you try to add the following code to your viewDidLoad method :

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;

It is quickly explained in Apple migrating to iOS 7 doumentation.

Upvotes: 3

Nicolas Buquet
Nicolas Buquet

Reputation: 3955

Did you try Apple recommendation about "Preventing the Status Bar from Covering Your Views": https://developer.apple.com/library/content/qa/qa1797/_index.html

And did you have a look at "UIBarPositioningDelegate": https://developer.apple.com/documentation/uikit/uibarpositioningdelegate

Upvotes: 40

macL0vin
macL0vin

Reputation: 183

I know that you have ViewController as Main VC. But if someone is using UITableviewController and having the same problem, this code solves the issue:

self.tableView.contentInset = UIEdgeInsetsMake(20.0f, 0.0f, 0.0f, 0.0f);

Upvotes: 1

dip
dip

Reputation: 139

For me solution was be shifting Navigation Bar to 20 point enter image description here

Upvotes: 0

Jeffrey Sun
Jeffrey Sun

Reputation: 8049

There is a built-in way to do this. Same as Joel Cave's answer, but elaborated:

Make your navigation bar have a Y origin of 20 points.

Then in the .h file:

@interface XYZViewController : UIViewController <UIBarPositioningDelegate>

And in the .m file:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationBar.delegate = self;
}

- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar { 
    return UIBarPositionTopAttached; 
}

Upvotes: 0

jbcaveman
jbcaveman

Reputation: 911

I'm surprised no one has hit on the right answer yet. UIBarPositioningDelegate works like a charm! Just make your view controller a UIBarPositioningDelegate and assign it as the bar's delegate. Position the bar 20 pixels from the top of your view. Then add this method to your view controller (only available in iOS7+):

- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar 
{ 
   return UIBarPositionTopAttached; 
}

Upvotes: 19

brian.clear
brian.clear

Reputation: 5327

Yes had same problem. followed all the step but no change.

Got it to work by making sure AutoLayout set up correctly for the whole screen not just the top view/toolbar as specified in

"Preventing the Status Bar from Covering Your Views" : https://developer.apple.com/library/ios/qa/qa1797/_index.html

At least for all Views just below the main Viewcontroller.view.

Upvotes: 0

mattsven
mattsven

Reputation: 23303

The solution to this is actually very simple. It involves manipulating UINavigationBar's center.y value, which is what UIKit natively uses in order to adjust UINavigationBar to the status bar's height. For simplicity's sake, I subclassed UINavigationBar and did the following:

@implementation MyNavigationBar

    - (void) setCenter:(CGPoint)center {
        // Anything less than or equal to 22 is something we don't want (below SB height)
        if(center.y > 22) [super setCenter:center];
    }

@end

Upvotes: 0

Nag Raja
Nag Raja

Reputation: 214

Try it, all navigationBars should be translucent is disable.

[self.navigationController.navigationBar setTranslucent:NO];

If you designed your view with a storyboard then you can solve the problem using XCode. Select the NavigationBar widget and uncheck "Translucent".

enter image description here

Upvotes: -1

josemando
josemando

Reputation: 573

I'm a little too late to the party, but since I faced the same issue and this was the first result that showed up in the search, I guess my answer could help other people :)

I fixed the problem by implementing

- (BOOL)shouldAutorotate
{
    return NO;
}

in the view controller that presents the modal.

Upvotes: -1

Sunil Adhyaru
Sunil Adhyaru

Reputation: 581

In iOS 7.0 UIViewController works by default this way. View will be full screen if you are using UIViewController inside UINavigationController and the navigationBar is visible.

If navigationBar is visible do following. ==>

self.edgesForExtendedLayout = UIRectEdgeNone

if navigationBar is hidden do following . ==>

Adjust all the UIView elements by shifting 20 points

If you use Interface builder, you can use iOS6/7 deltas: First, "view as iOS 6.0", then set a delta of "20" to achieve the +20 offset in iOS 7

Upvotes: 26

grigorievs
grigorievs

Reputation: 162

I fixed such a problem using answer from this post: iOS 7 | Navigation bar / Toolbar buttons very close to status bar

Using Autolayout you should ignore setting a new Frame. You should add a Top Space Constraint equal to 20 for the TopBar for iOS 7.

Upvotes: 3

Stephen Johnson
Stephen Johnson

Reputation: 5121

I had a similar issue with a "hamburger" menu button that slide the main view controller over and had a menu view controller on the side. I found that the menu view controller's navigation bar was not aware if the status bar was shown or not. I fixed it by posting a notification when the status bar was shown and hiddden then doing

[self.navigationController setNavigationBarHidden:YES/NO animated:NO];

in the menu's view controller.

Upvotes: 4

jaredsinclair
jaredsinclair

Reputation: 12707

I have answered this problem at length in this answer to a similar question. The short answer is this: there is no way to get the automatic status bar layout behavior you're used to from iOS 6 and earlier. You'll have to design around it, or find a way to simulate the old style (I cover both approaches).

I strongly advise you not to make manual adjustments to the navigation bar frame. Let UINavigationController handle that yourself. Most likely, your problem is that that your navigation controller's view's frame isn't equal to the UIScreen's bounds.

Upvotes: 1

Related Questions