5

I'm developing an iOS 6 and 7 app that requires the navigation bar to be taller than the usual 44/64 pts I've searched high and low and so far it seems the cleanest solution is to use a category (or subclass) and implement the - (CGSize)sizeThatFits:(CGSize)size method to return a different size.

This works fine in just making , however doing this causes all the items inside to rest at the bottom of the navigation bar, while I'd like to have them centered. I have tried using the Appearance Proxy protocol to define vertical offsets for the buttons, specifically this code

[[UIBarButtonItem appearance] setBackgroundVerticalPositionAdjustment: -10    forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonBackgroundVerticalPositionAdjustment: -10 forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment: -10 forBarMetrics: UIBarMetricsDefault];

Works just fine on iOS 6, producing this result

iOS 6

But doesn't work on iOS 7, giving me this instead.

iOS 7

I have read around that under iOS 7 the adjustments only work when using custom views but it seems odd to me, especially considering that setBackButtonTitlePositionAdjustment:forBarMetrics: actually moves the text for the back button up, but not the chevron and that the title actually does nudge up.

I've also tried going for a subclassing route, using layoutSubviews to move down the views inside the UINavigationBar. This works, but of course when a new view controller is pushed the buttons jump around during the transition.

Am I missing something? Thanks in advance

UPDATE I have edited the description to make it clearer that my issue is with what's inside the bar, not the bar itself.

Haiku Oezu
  • 897
  • 1
  • 8
  • 19

5 Answers5

8

The cleanest solution I've found to this problem was to use my own subclass of UINavigationBar and center the buttons vertically by overriding the layoutSubviews method:

- (void)layoutSubviews
{
    [super layoutSubviews];

    NSArray *subviews = self.subviews;
    for (UIView *view in subviews) {
        if ([view isKindOfClass:[UIButton class]]) {
            view.frame = ({
                CGRect frame = view.frame;
                CGFloat navigationBarHeight = CGRectGetHeight(self.frame);
                CGFloat buttonHeight = CGRectGetHeight(view.frame);
                frame.origin.y = (navigationBarHeight - buttonHeight) / 2.0f;
                frame;
            });
        }
    }
}

To make a UINavigationController use your subclass of UINavigationBar you can use the initWithNavigationBarClass:toolbarClass: initialiser:

UINavigationController *navigationController = [[UINavigationController alloc] initWithNavigationBarClass:[MyNavigationBar class] toolbarClass:nil];
Tiago
  • 3,113
  • 2
  • 31
  • 45
  • 1
    I have investigated this route too, but it causes cosmetic issues when pushing and popping view controllers. – Haiku Oezu Jan 20 '14 at 11:02
  • I'm not having any problems pushing/popping, but maybe that is because I have a `UINavigationBar` with the standard height. In iOS 7, however, my `UIBarButtonItem`s were not being centered vertically correctly and this solved it. Sorry I couldn't be of help. – Tiago Jan 21 '14 at 17:28
  • 1
    It's OK, I think this one simply cannot be done. I ended up using a horrible workaround that involves creating buttons with custom UIView's that are as high as the navigation bar and adding buttons there. It ain't pretty, but it works – Haiku Oezu Jan 22 '14 at 09:55
  • 3
    I like this `view.frame = ({ expression; })` sorcery! Didn't know you could do that. ;-) – Ricardo Sanchez-Saez Jul 03 '14 at 12:59
  • 1
    Works gread for buttons but have issues with titleView. If I go with repositioning all the views - it messes up the layout and repositions the status bar background view as well. Do you have any solution for repositioning titleView? – Alexander Telegin Feb 17 '17 at 14:42
  • I just found a solution for centering the titleView as well. In the view controller, just assign it a tag of a random number such as 999, and then when checking if the view is UIButton, add an or statement to check if it has a tag of 999. – Kiran Jun 21 '17 at 22:09
0

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 Documentation : https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/AppearanceCustomization.html

//it's leave the status-bar height above.

Renish Dadhaniya
  • 10,642
  • 2
  • 31
  • 56
  • U can Also use Delta property using down your view 20pixels below.It's just happen for because ios7 into full screen give to developer for manage itself. – Renish Dadhaniya Jan 02 '14 at 12:43
  • No, this isn't about the navigation bar overlapping the status bar... I've got that part already handled by my storyboards. What I need is to properly center the contents of the navigation bar – Haiku Oezu Jan 02 '14 at 13:10
0

There is a quick crack to this, unless you find the proper solution, this would definitely work ;)

  • Check for system running iOS7.

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
    {
       // Add below code
    }
    
  • Add Label to the Navigation Bar :

    UINavigationBar *bar = [self.navigationController navigationBar];
    
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(110, 55, 150, 20)]; //Set the frame appropriate to your screen
    label.backgroundColor = [UIColor clearColor];
    label.font = [UIFont boldSystemFontOfSize:14];
    label.adjustsFontSizeToFitWidth = NO;
    label.textAlignment = UITextAlignmentCenter;
    label.textColor = [UIColor blackColor];
    label.highlightedTextColor = [UIColor blackColor];
    [bar addSubview:label];
    
barley
  • 4,403
  • 25
  • 28
Ajay Sharma
  • 4,509
  • 3
  • 32
  • 59
  • 1
    But this simply makes the bar bigger right? My issue is with the vertical positioning of the items inside – Haiku Oezu Jan 02 '14 at 13:25
  • Nopes .. did you tested it ? This won't increase the height, instead it will allow you to set the position of label in the bar. – Ajay Sharma Jan 03 '14 at 05:51
  • 1
    Yeah, I tested it. But the title label is fine (``setTitleVerticalPositionAdjustment`` does the job fine), my problem is with the back button resting at the bottom of the bar instead of the middle (on iOS 7, iOS 6 works just fine) – Haiku Oezu Jan 03 '14 at 18:27
0

Swift 3 version of Tiago his answer

override func layoutSubviews() {
    super.layoutSubviews()

    subviews.filter { (subview) -> Bool in
        return subview is UIButton
    }.forEach { (subview) in
        subview.center.y = frame.height / 2
    }
}

Adjusting the titleView vertical postion

setTitleVerticalPositionAdjustment(-10, for: .default)
Lloyd Keijzer
  • 1,229
  • 1
  • 12
  • 22
-1

You can change size of navigation bar with just changing it's frame:

CGRect navigationBarFrame = self.navigationController.navigationBar.frame;

kjhkjhkjh
  • 412
  • 3
  • 12
  • It may be quicker but it doesn't fix the issue with the buttons sticking to the bottom of the navigation bar – Haiku Oezu Jan 02 '14 at 13:14