如何自定义 UINavigationBar 的高度

UINavigationBar 官方给出的高度是44,一般开发过程中,我们都是使用默认的高度。但是有些需求,让我们不得不想办法去修改导航栏的高度,比如下面的场景

这个导航栏的高度达到了84,使用默认的是没有办法完成的,所以我们需要尝试修改UINavigationBar,来完成这个需求。

我们只需要关心高度增加了多少,这里我们首先定义一个变量来表示增加的高度

const CGFloat NavigationBarHeightIncrease = 40.f;

通过重写 - (CGSize)sizeThatFits:(CGSize)size 这个方法,来修改UINavigationBar的高度,代码如下:

- (CGSize)sizeThatFits:(CGSize)size
{
    CGSize navigationBarSize = [super sizeThatFits:size];
    
    navigationBarSize.height += NavigationBarHeightIncrease;
    
    return navigationBarSize;
}

这个时候尝试运行 看一下效果,如下:


我们会发现高度确实是改变了,但是上面的item和title的位置不是我们想要的,所以接下来需要考虑如何修改他们的位置。

我们先在layoutSubviews函数里打印一下所有的subView,看一下层级

<_UINavigationBarBackground: 0x7fa158e69da0; frame = (0 -20; 320 104); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fa158e69f20>>

<UIButton: 0x7fa158d4bc60; frame = (269 44; 35 35); opaque = NO; animations = { opacity=<CABasicAnimation: 0x7fa158d6f350>; }; layer = <CALayer: 0x7fa158d6c2d0>>

<UIButton: 0x7fa158d4f970; frame = (16 47; 30 30); opaque = NO; animations = { opacity=<CABasicAnimation: 0x7fa158d6f2d0>; }; layer = <CALayer: 0x7fa158d3a9c0>>

<UIView: 0x7fa158d6e1b0; frame = (0 0; 269 84); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x7fa158d6d170>>

<UIView: 0x7fa158d6b1d0; frame = (46 0; 274 84); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x7fa158d47120>>

_UINavigationBarBackIndicatorView: 0x7fa158e6aec0; frame = (8 51.5; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fa158e6ab20>>

<UINavigationItemView: 0x1090a4f40; frame = (136.5 8; 47 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x10909a0f0>>
| <UILabel: 0x1090a5440; frame = (0 41; 47 22); text = 'Home'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x10909a660>>

这里的左右两个按钮 分别对应两个UIButton 类, 中间的title对应UINavigationItemView类,我想的是,能不能去改变他们的frame,达到修改位置的目的,于是,代码如下:

- (void)layoutSubviews {
    [super layoutSubviews];
    
    NSArray *classNamesToReposition = @[@"UINavigationItemView", @"UINavigationButton",@"UIButton"];
    
    for (UIView *view in self.subviews) {
        
        if ([classNamesToReposition containsObject:NSStringFromClass([view class])]) {
            
            CGRect frame = view.frame;
            frame.origin.y -= NavigationBarHeightIncrease;
            
            view.frame=frame;
        }
    }
}

运行后,结果如下:

title的位置并没有改变,后来查看了资料后,发现可以通过这种方法可以修改title的位置

[self setTitleVerticalPositionAdjustment:-NavigationBarHeightIncrease forBarMetrics:UIBarMetricsDefault];

效果如下


看起来似乎达到了我们想要的效果,正当我要欣喜若狂的时候,发现跳转的时候,位置还是回到了原来的地方,并且跳转的时候,能明显感觉到frame的变化,这种方法还是不可取。

下面我们来换种思路,可以将整个UINavigationBar的transform,在初始化的时候,整体做一个位移处理,代码如下:

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

- (id)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    
    if (self) {
        [self initialize];
    }
    
    return self;
}

- (void)initialize {
    
    [self setTransform:CGAffineTransformMakeTranslation(0, -(NavigationBarHeightIncrease))];
}

运行后发现效果如图:

位置的问题是解决了,但是高度又看起来和刚开始一样了,其实这里我们就需要修改UINavigationBar最下面的View的frame 就可以了,具体代码如下:

- (void)layoutSubviews{
    [super layoutSubviews];

//这里底层的View iOS 9.0以上好像是_UIBarBackground 类  以下是_UINavigationBarBackground  ,所以需要判断两个
    NSArray *classNamesToReposition = @[@"_UIBarBackground",@"_UINavigationBarBackground"];
    
    for (UIView *view in [self subviews]) {
        if ([classNamesToReposition containsObject:NSStringFromClass([view class])]) {
            
            CGRect bounds = [self bounds];
            CGRect frame = [view frame];
            frame.origin.y = bounds.origin.y + NavigationBarHeightIncrease - 20.f;
            frame.size.height = bounds.size.height + 20.f;
            
            [view setFrame:frame];
        }
    }
}

效果如下:

至此 ,已经完美的实现了UINavigationBar高度变化,但是两边的按钮和title不受影响

下面给出Demo地址 ,喜欢的给个星--->点我跳转

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • iphone开发笔记 退回输入键盘 - (BOOL) textFieldShouldReturn:(id)text...
    爱易寒曲易散阅读 3,759评论 0 1
  • 1,Search Bar 怎样去掉背景的颜色(storyboard里只能设置background颜色,可是发现cl...
    以德扶人阅读 7,530评论 2 50
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,216评论 4 61
  • 北京的高温模式似乎已经告一段落了,所以,我要去长沙找桑拿天了。80-90的湿度,36-37的温度,还是很酸爽的。不...
    奔跑的马齿苋阅读 14,973评论 5 11
  • 1 我是一名来自内蒙古的学员,几经周折,在谦德弘愿的帮助下,最后终于参加了此次山东亲近圣贤智慧游学,来到了山东圣城...
    秦东魁阅读 2,880评论 0 0