Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Center elements vertically inside UINavigationBar with custom height

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.

like image 260
Haiku Oezu Avatar asked Jan 02 '14 12:01

Haiku Oezu


1 Answers

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];
like image 189
Tiago Avatar answered Nov 11 '22 19:11

Tiago