以编程方式在Swift中更改导航栏高度

3

我想要制作一个更高的导航栏,我正在尝试使用UINavigationBar的子类来实现。

这是我的UINavigationBar子类:

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

在我的视图控制器中,它嵌入了一个导航控制器。在viewDidLoad()函数中,我编写了以下代码。
self.navigationController!.setValue(TallerNaviBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 87)), forKeyPath: "navigationBar")

没有报错,但是当我运行代码时什么都没有。一个完全空白的视图。在此输入图片描述。有什么建议吗?或者其他改变高度的方法?谢谢。

这是Swift的答案,很好的点赞,不用谢。 - Larry Pickles
@Larcerax。感谢您的回答。但是我的声望值仅为8,这意味着我不能进行负投票。很抱歉您遭受了负评分,但那不是我。 - Aiden
所以,第一个答案是正确的答案,即:self.superview!.frame.size.width, 87。试一下,你会发现它应该可以正常工作。如果您知道如何在Swift中进行类型转换,请尝试一下。对于先入为主的看法,我很抱歉。 - Larry Pickles
@Larcerax。我不能为您点赞,否则会导致您的损失。点赞的最低要求是15,而踩的最低要求是125。http://stackoverflow.com/help/privileges/vote-up。http://stackoverflow.com/help/privileges/vote-down。 - Aiden
@Larcerax 它可以工作了!谢谢! - Aiden
显示剩余3条评论
2个回答

9

iOS 11及以上版本的更新

苹果不希望你更改导航栏高度,所以请不要触碰它。 请参考以下链接: https://openradar.appspot.com/32912789https://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
    }
}

我不会Swift,但答案很简单,这里是ObjC

- (CGSize)sizeThatFits:(CGSize)size {

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

}

这是我用Swift的解释:

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

你将面临的问题不是这个方法,这是容易的一部分,问题在于强制导航控制器始终使用此导航栏。

我会对IOS中的所有内容进行子类化和调整大小,包括导航控制器和选项卡控制器。为了强制所有导航控制器都使用此导航栏,您必须子类化一个navigationController,并且仅在整个应用程序中使用此navigationcontroller。以下是子类化的工作原理,这是Obj C,因此您需要翻译它:

@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"];
}

这是一行可以帮助您完成任务的代码:
   [self setValue:[[NSHNavigationBar alloc]init] forKeyPath:@"navigationBar"];

噢,对了,请确保你正在子类化导航栏,你说你正在做,但这是如何实现的,很简单:

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

}

因此,概括地说,子类化UINavigationBar和UINavigationController即可进行设置,这将允许您在任何时候操作导航栏,您还可以对视图控制器的导航栏进行强制转换,这有点疯狂并且会让很多人感到困惑,但是下面就是实现方法:

-(CustomNavigationBar *)navBar {

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

在您的视图控制器中添加上述内容,然后您可以通过以下方式调用它:
[[self navBar] setBackGroundColor:[UIColor blueColor]];

如果您希望将导航控制器转换为自定义导航栏,可以成功地进行类型转换。如果您想从这里更改导航栏的高度,则可以执行以下操作:


1
不适用于iOS 11。我按上述描述创建了UINavigationController和UINavigationBar的子类。在Storyboard中,将UINavigationController和UINavigationBar的类名更改为相应的子类名称。但高度没有改变。 - crypt
1
@Vakas,这个已经不再支持了,请看这里:https://forums.developer.apple.com/thread/88202#274620 和这里:https://openradar.appspot.com/32912789。苹果不希望你去改变导航栏的高度,所以最好别碰它,告诉你的客户别再瞎搞了。 - Larry Pickles

8

这里提供了一个基于最小化子类化的简单Swift 3解决方案。首先需要子类化UINavigationBar:

class CustomNavigationBar: UINavigationBar {
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        let newSize :CGSize = CGSize(width: self.frame.size.width, height: 54)
        return newSize
    }
}

使用代码创建导航控制器,并使用接受自定义导航栏类的初始化程序。
let nav = UINavigationController(navigationBarClass: CustomNavigationBar.self, 
                                 toolbarClass: nil)

所有现有的UINavigationBar行为都会被保留,同时采用您自定义的高度。


1
如何在UIStoryboard中设置自定义导航栏类?我尝试更改类名,但它不起作用。 - Hemang
1
sizeThatFits在iOS11中不再支持。 - NiBE
如何设置rootViewController? - seyha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接