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)