如何自定義 UINavigationBar 的高度

UINavigationBar 官方給出的高度是44,一般開發(fā)過(guò)程中,我們都是使用默認(rèn)的高度。但是有些需求,讓我們不得不想辦法去修改導(dǎo)航欄的高度,比如下面的場(chǎng)景

這個(gè)導(dǎo)航欄的高度達(dá)到了84,使用默認(rèn)的是沒(méi)有辦法完成的,所以我們需要嘗試修改UINavigationBar,來(lái)完成這個(gè)需求。

我們只需要關(guān)心高度增加了多少,這里我們首先定義一個(gè)變量來(lái)表示增加的高度

const CGFloat NavigationBarHeightIncrease = 40.f;

通過(guò)重寫 - (CGSize)sizeThatFits:(CGSize)size 這個(gè)方法,來(lái)修改UINavigationBar的高度,代碼如下:

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

這個(gè)時(shí)候嘗試運(yùn)行 看一下效果,如下:


我們會(huì)發(fā)現(xiàn)高度確實(shí)是改變了,但是上面的item和title的位置不是我們想要的,所以接下來(lái)需要考慮如何修改他們的位置。

我們先在layoutSubviews函數(shù)里打印一下所有的subView,看一下層級(jí)

<_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>>

這里的左右兩個(gè)按鈕 分別對(duì)應(yīng)兩個(gè)UIButton 類, 中間的title對(duì)應(yīng)UINavigationItemView類,我想的是,能不能去改變他們的frame,達(dá)到修改位置的目的,于是,代碼如下:

- (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;
        }
    }
}

運(yùn)行后,結(jié)果如下:

title的位置并沒(méi)有改變,后來(lái)查看了資料后,發(fā)現(xiàn)可以通過(guò)這種方法可以修改title的位置

[self setTitleVerticalPositionAdjustment:-NavigationBarHeightIncrease forBarMetrics:UIBarMetricsDefault];

效果如下


看起來(lái)似乎達(dá)到了我們想要的效果,正當(dāng)我要欣喜若狂的時(shí)候,發(fā)現(xiàn)跳轉(zhuǎn)的時(shí)候,位置還是回到了原來(lái)的地方,并且跳轉(zhuǎn)的時(shí)候,能明顯感覺(jué)到frame的變化,這種方法還是不可取。

下面我們來(lái)?yè)Q種思路,可以將整個(gè)UINavigationBar的transform,在初始化的時(shí)候,整體做一個(gè)位移處理,代碼如下:

- (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))];
}

運(yùn)行后發(fā)現(xiàn)效果如圖:

位置的問(wèn)題是解決了,但是高度又看起來(lái)和剛開始一樣了,其實(shí)這里我們就需要修改UINavigationBar最下面的View的frame 就可以了,具體代碼如下:

- (void)layoutSubviews{
    [super layoutSubviews];

//這里底層的View iOS 9.0以上好像是_UIBarBackground 類  以下是_UINavigationBarBackground  ,所以需要判斷兩個(gè)
    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];
        }
    }
}

效果如下:

至此 ,已經(jīng)完美的實(shí)現(xiàn)了UINavigationBar高度變化,但是兩邊的按鈕和title不受影響

下面給出Demo地址 ,喜歡的給個(gè)星--->點(diǎn)我跳轉(zhuǎn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iphone開發(fā)筆記 退回輸入鍵盤 - (BOOL) textFieldShouldReturn:(id)text...
    愛易寒曲易散閱讀 682評(píng)論 0 1
  • 1,Search Bar 怎樣去掉背景的顏色(storyboard里只能設(shè)置background顏色,可是發(fā)現(xiàn)cl...
    以德扶人閱讀 2,874評(píng)論 2 50
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,103評(píng)論 4 61
  • 北京的高溫模式似乎已經(jīng)告一段落了,所以,我要去長(zhǎng)沙找桑拿天了。80-90的濕度,36-37的溫度,還是很酸爽的。不...
    奔跑的馬齒莧閱讀 14,935評(píng)論 5 11
  • 1 我是一名來(lái)自內(nèi)蒙古的學(xué)員,幾經(jīng)周折,在謙德弘愿的幫助下,最后終于參加了此次山東親近圣賢智慧游學(xué),來(lái)到了山東圣城...
    秦東魁閱讀 399評(píng)論 0 0

友情鏈接更多精彩內(nèi)容