UINavigationBar的高度在蘋果官方的SDK中是固定的44個點,但是實際項目中我們卻有可能遇到這樣的情況,如下圖:
這樣的一個UINavigationBar的高度達到了84個點,這就需要我們自定義系統自帶的UINavigationBar的高度,但是系統並沒有直截了當的方法來調整這個NavigationBar的Height,於是我進行了以下的嘗試。
在需要進行調整的那個ViewController類的ViewWillApplear這個方法對 self.navigationController.navigationBar的frame進行賦值,其中frame.size.height變為我 們需要的新高度(本例中為84),然后在ViewWillDisappear這個方法中將frame再改回去就可以了。
注:這里將代碼寫在ViewWillAppear/DisAppear里面的原因是根據這個自定義高度UINavigationBar只在某一 個界面出現,如果你所有的UINavigationBar的高度是統一的,那么就沒必要這么寫,只需要寫在第一次出現的ViewController的 ViewDidLoad消息里面就可以了。
代碼如下:
1
2
3
4
5
6
7
8
9
10
11
|
- ( void ) viewWillAppear : ( BOOL ) animated { [ super viewWillAppear :animated ] ; CGRect rect = self . navigationController . navigationBar . frame ; self . navigationController . navigationBar . frame = CGRectMake ( rect . origin . x , rect . origin . y , rect . size . width , 84 ) ;
}
- ( void ) viewWillDisappear : ( BOOL ) animated { [ super viewWillDisappear :animated ] ; CGRect rect = self . navigationController . navigationBar . frame ; self . navigationController . navigationBar . frame = CGRectMake ( rect . origin . x , rect . origin . y , rect . size . width , 44 ) ;
}
|
OK,運行!UINavigationBar的高度正確地發生變化,事情就這么愉快地解決了!等等,導航欄上的標題和返回按鈕的位置卻都貼到最下面了,如下圖:
為什么會是這樣?發生了什么?我也不知道!但是現在很明顯就是需要我們去調整這兩個“UIView”的frame,把他們向上移動40個點,為之后要添加的其他控件留出空間。很簡單,對吧?
然后,數個小時過去后……
我靠,這些貨特么根本不是UIView嘛!
返回按鈕是UIBarButtonItem,繼承自UIBarItem,UIBarItem繼承自NSObject,標題這個就更悲劇了,如果 你默認使用ViewController的title屬性做為標題(本例就是),那么self.navigationItem.titleView這個值 為nil,更改nil的frame什么事情也不會發生。
這期間我試過各種非正常手段去找到他們,包括遍歷UINavigationBar的view hierarchy(視圖層級),試圖使用UIBarButtonItem的私有變量,嘗試修改UIBarButtonItem的 CustomView.frame等……都無功而返。
然后開始上Google搜索,StackOverflow一片找,SO上果然大神雲集,問題的解答也相當高大上。
答案基本上有2種:
1、不用系統的NavigationBar啦,咱們自定義一個就好啦,然后重載layoutSubView里面的怎樣怎樣雲雲。
2、這個簡單,我寫了個NavigationBar的分類(Category),里面加個什么消息xxx。
小菜我一看到自定義控件神馬的立即就給外國大爺們跪了,Category什么的更是從來沒用過……其實我只需要更改一下這兩個控件的高度而已,用不用這么暴力?
於是我開始查文檔,終於被我找到下面這兩個消息:
UINavigationBar下:
- (void)setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
官方描述: Sets the title’s vertical position adjustment for given bar metrics. 調整某個BarMetrics(這個不知道怎么翻譯)下標題的垂直位置。
UIBarButtonItem下:
- (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
官方描述: Sets the background vertical position offset for given bar metrics.This offset is used to adjust the vertical centering of bordered bar buttons within the bar. 調整某個BarMetrics(這個不知道怎么翻譯)下背景的垂直位置的偏差值,這個偏差值用來調整該圓角按鈕的垂直中心在Bar內的位置。
OhMyGod,終於找到組織了!趕緊試一下,還是剛才的ViewController,在ViewWillAppear這個消息中再加上這么兩句:
1
2
|
[ self . navigationController . navigationBar setTitleVerticalPositionAdjustment : - 40.0 forBarMetrics : UIBarMetricsDefault ] ; [ self . navigationItem . leftBarButtonItem setBackgroundVerticalPositionAdjustment : - 40.0 forBarMetrics : UIBarMetricsDefault ] ; |
注:這里使用leftBarButtonItem是因為我使用了自定義圖片的返回按鈕,這時leftBarButton就替代了backBarButton。
不要忘了在ViewWillDisappear的時候再把標題的位置調整回來,不然當標題就會跳到屏幕的最上方了;另一方面,返回按鈕卻不用設置了,這兩行代碼的作用機制不一樣,返回按鈕只和當前的ViewController有關:
1
|
[ self . navigationController . navigationBar setTitleVerticalPositionAdjustment : 0.0 forBarMetrics : UIBarMetricsDefault ] ; |
運行結果:
太棒啦!終於成功了!標題和返回按鈕的垂直位置按照我們設置的向上移動了40個點!
后面的事情就簡單了,按照設計濕GG或者設計師MM的要求把相應的UI控件加到self.navigationController.navigationBar中,收工!
注:上述運行結果的前提是使用自定義圖片的leftBarButtonItem作為返回按鈕替代系統默認的 backBarButtonItem,並且你的leftBarButtonItem是使用 initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action這個方法創建的(原因我后面會講)。換句話說,在你的ViewController或者它的父類的 ViewDidLoad方法里,應該有類似下面的兩行代碼:
1
2
|
UIBarButtonItem * item = [ [ UIBarButtonItem alloc ] initWithImage : [ UIImage imageNamed : @ “這里是你的某個圖片名" ] style : UIBarButtonItemStyleBordered target : self action : @ selector ( 你的某個方法名 ) ] ; self . navigationItem . leftBarButtonItem = item ; |
如果你的需求剛好能用這個方法解決,那么恭喜你,因為小菜能拿出的干貨就只有這么多了,后面的就全是困惑了……orz
做為一個iOS Level1的菜鳥,在費了好大的勁終於找到問題的解決方法之后,欣喜是肯定的,想得瑟一下是必然的,於是飄飄乎就想把相關的方法研究研究,搞個通用的解決方案出來。於是,噩夢開始了……
N多個小時過去了,毛個解決方案沒搞出來,卻搞出來了很多個問題……
問題1:系統默認的導航欄返回按鈕垂直位置無法調節。
當返回按鈕使用系統默認的backBarButtonItem的時候,使用UIBarButtonItem的- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics來調整它的垂直位置,不起作用。
我進行了各種嘗試,但是backBarButtonItem一直是nil,文檔上說它會根據上一個ViewController的title屬 性來創建這個按鈕,但是我找不到這個時機來調整執行上面這個消息。更准確的問題可能是,下圖中的這個消息到底應該怎么用才能看到效果呢?
問題2:自定義的返回按鈕在導航欄中的垂直位置僅在某一種情況下可以調節。
后來我又發現,即使不用系統默認地返回按鈕,使用自定義的leftBarButtonItem,也只在使用 initWithImage:style target:action:這個方法創建的UIBarButtonItem時生效,使用其他init方法情況一律無效。至於什么原因不明覺厲。
這兩個問題我百撕不得姐,求大家指教,提前說聲謝謝!
copy from http://iosinit.com/?p=757