Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

ios - Programmatically change height of navigation bar in swift

I want to make a taller navigation bar and I am trying to do this using a subclass of UINavigationBar.

Here is my subclass of UINavigationBar:

import UIKit
class TallerNaviBar: UINavigationBar {
    override func sizeThatFits(size: CGSize) -> CGSize {
        var newSize:CGSize = CGSizeMake(size.width, 87)
        return newSize
    }
}

And in my ViewController which is embedded in a navigation controller, I write the following code in the viewDidLoad() function

self.navigationController!.setValue(TallerNaviBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 87)), forKeyPath: "navigationBar")

There is no error reported, but I get nothing when I run the code. A completely blank view. enter image description here.

Any suggestion? Or some other way of changing the height? Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

update for iOS 11 and beyond

apple doesn't want you messing with the navigation bar height, so don't touch it see here: https://openradar.appspot.com/32912789 and here: https://forums.developer.apple.com/thread/88202#274620

class TallerNaviBar: UINavigationBar {
    override func sizeThatFits(size: CGSize) -> CGSize {
        var newSize:CGSize = CGSizeMake(self.superview!.frame.size.width, 87)
        return newSize
    }
}

I don't do swift, but the answer is easy, here's ObjC

- (CGSize)sizeThatFits:(CGSize)size {

         return CGSizeMake([self superview].frame.size.width, 40);

}

Here's my interpretation in Swift:

import UIKit
class TallerNaviBar: UINavigationBar {
    override func sizeThatFits(size: CGSize) -> CGSize {
        var newSize:CGSize = CGSizeMake(superview.width, 87)
        return newSize
    }
}

The problem you will have isn't with this method, this is the easy part, the problem is forcing the navigation controller to always use this navigation bar

I subclass and resize everything in IOS, including navigation controllers and tabbarcontrollers, in order to enforce that all navigation controllers use this navigation bar, you must subclass a navigationController and only use this navigationcontroller throughout your app, here's how the subclass works, this is Obj C, so you'll have to translate it:

@interface NSHNavigationController () <UINavigationBarDelegate, UINavigationControllerDelegate>
{

}

@implementation NSHNavigationController

#pragma mark Initialization

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self NSHSetupNavigationController];
    }
    return self;
}

- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
{
    self = [super initWithNavigationBarClass:navigationBarClass toolbarClass:toolbarClass];
    if (self) {
        [self NSHSetupNavigationController];
    }
    return self;
}

- (id)initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super initWithRootViewController:rootViewController];
    if (self) {
        [self NSHSetupNavigationController];
    }
    return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        [self NSHSetupNavigationController];
    }
    return self;
}

- (void)dealloc
{
    [self setInternalDelegate:nil];
    [self setExternalDelegate:nil];
}

#pragma mark Setup

- (void)NSHSetupNavigationController
{
    [self setValue:[[NSHNavigationBar alloc]init] forKeyPath:@"navigationBar"];
}

this is the line that will do it for you:

   [self setValue:[[NSHNavigationBar alloc]init] forKeyPath:@"navigationBar"];

Oh yeah, and make sure you are subclassing the nav bar, you said you were, but here's how you do it, it's simple:

#import "NSHNavigationBar.h"

@implementation NSHNavigationBar
- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        NSDictionary *attributes = @{NSForegroundColorAttributeName:[UIColor whiteColor],
                                     NSFontAttributeName:fontMagicForRegularNSHFont};
        [self setTitleTextAttributes:attributes];
        [self setTranslucent:true];
        [self setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}
- (CGSize)sizeThatFits:(CGSize)size {

    return CGSizeMake([self superview].frame.size.width, heightResizer(40));

}

- (void)layoutSubviews {

    [super layoutSubviews];

}

So, in summary, subclass both the UINavigationBar and the UINavigationController and you are set, this will allow you to manipulate the navigation bar whenever you'd like, you can also type cast your view controller's navigation bars, this is a little nuts and will confuse a lot of people, but here it goes:

-(CustomNavigationBar *)navBar {

    return (id)[self.navigationController navigationBar];
}

put the stuff above in your view controller and then you call it like this:

[[self navBar] setBackGroundColor:[UIColor blueColor]];

This will successfully typecast your navigationcontroller to be your custom navigation bar, if you want to change the height of the nav bar from here, then you can do something like this:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...