Center elements vertically inside UINavigationBar

2019-04-09 04:41发布

问题:

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

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

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.

回答1:

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];


回答2:

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.



回答3:

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];
    


回答4:

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)


回答5:

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

CGRect navigationBarFrame = self.navigationController.navigationBar.frame;