UINavigationBar和UINavigationItem

今天修復了一個小bug, 由於一個viewController的右邊有3個按鈕,在手機上和中間的title離得有點近了. 大致是這樣 , 按鈕是隨便寫的 , 沒加圖🤣,


通過這樣設置的 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView: rightView]; rightView是一個普通的UIView,上面放了3個button , 
既然右邊按鈕距離中間的title太近了, 而且 "更多" 右邊還有一點小空隙 , 就想改變rightBarButtonItem距離右邊的距離,讓3個按鈕往右擠擠,大致是做成這樣的.

好了, 現在知道了現狀,也知道的目的.那就開始做了.


一開始的想法是 通過加一個UIBarButtonSystemItemFixedSpace的item,把這個設置爲負值,這樣就可以把rightView右移了, 代碼大致是這樣


UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]   
                               initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace   
                                   target:nil action:nil];  
/**  
 *  width爲負數時,相當於btn向右移動width數值個像素,由於按鈕本身和邊界間距爲5pix,所以width設爲-5時,間距正好調整  
 *  爲0;width爲正數時,正好相反,相當於往左移動width數值個像素  
 */  
negativeSpacer.width = -5;  
self.navigationItem.rightBarButtonItems = @[negativeSpacer, rightView, ];  

可惜,理想很美好,現實很骨感, 把 negativeSpacer.width 設置成一個正值倒是挺管用的 ; 設置爲-20, 一點變化也沒有 , 估計是在iOS的某次更新後系統做了處理了 , 好吧,下一條路.


第二種思路 ,  UIBarButtonItem 裏面的文檔看了好久 , UIBarButtonItem都不是UIView的子類 , 沒有可以設置邊距的東西 ,   後面甚至想到了重寫 navigationController的viewDidLayoutSubviews , 在那裏面重寫設置frame, 但是想想這個影響的頁面太多了,判斷會很多 , 也不太能拿到 這個rightView ,  得不償失.

就在失望之際 , 發現了UINavigationBar *navigationBar , 這是UIView的一個子類, 或許可以在這個上面動動手腳 , 於是 

    UIView * rightView =  [[UIView alloc] initWithFrame:CGRectMake(Screen_Width-130, 0, 130, 44)];
    [rightView addSubview:videoButton];
    [rightView addSubview:micButton];
    [rightView addSubview:moreBtn];
   
    [self.navigationController.navigationBar addSubview:rightView];

運行之後 , 果然變成了想要的樣子. 右邊貼邊了 , 而且想設置多少就是多少, 美滋滋.

但是在pop的時候發現了一個問題 , 已經pop到上一個界面了, 但是這3個按鈕沒有消失 , 只要將信將疑的在viewWillDisappear裏 , 把[rightView removeFromSuperview] , 事實果然有效, pop之後, 這3個按鈕也消失了. nice.


雖然功能完成了,但是UINavigationBar和UINavigationItem是什麼關係呢? 自然要一探究竟.

一、導航條navigation bar

1、導航條navigationbar屬於導航控制器,一個導航控制器只有一個導航條。

2、在一個導航控制器push新頁面和pop頁面時,導航條是同一個。

3、在一個視圖控制器內改變了導航條的樣式,其它控制器的導航條的樣式也會改變,也說明了導航條屬於導航控制器,而不是每個視圖控制器都有一個導航條。

4、導航條的層級結構

navigationbar層級

 

 

UINavigationBar

 

UIBarBackground

UIBarBackground視圖是比UINavigationBar視圖要大

二、導航欄與self.view佈局問題

iOS開發過程當中遇到導航欄遮擋佈局的問題,在頁面跳轉後,下級頁面也會被導航欄所遮擋。

如果你的容器是UINavigationController,在iOS7之前導航欄默認爲半透明的,佈局默認會從頂部開始,所以會被遮擋。

解決方案1:

在iOS7 UIViewController引入了一個新的屬性edgesForExtendedLayout,默認爲UIRectEdgeAll,即鋪滿整個屏幕

self.edgesForExtendedLayout =UIRectEdgeNone;設置後佈局從導航欄下開始

解決方案2:

self.navigationController.navigationBar.translucent =NO;

將導航欄設置爲不透明後,佈局會自動放到導航欄以下。

三、導航欄與self.view高度問題

在帶有導航欄的控制器中,viewDidLoad方法執行前後self.view的高度是不一致的,執行前爲屏幕的高度,而執行後則減去導航欄+狀態欄的高度。

//以iphone6爲例

- (void)viewDidLoad {

[super viewDidLoad];

NSLog(@"執行前%d",CGRectGetHeight(self.view.frame));

}

- (void)viewDidAppear:(BOOL) animated{

[super viewDidLoad];

NSLog(@"執行後%d",CGRectGetHeight(self.view.frame));

}

log:

執行前667

執行前603

準確說應該是viewWillAppear和viewDidAppear之間self.view高度發生變化

在viewWillAppear時視圖控件佈局還沒有設置,因此對於一個VC,self.view就是最原始的狀態,從屏幕頂端開始,高度爲ScreenHeight

在viewDidAppear時視圖已經顯示在屏幕上了,self.view以及子視圖的佈局已經設置好了,而self.view由於導航欄不透明或其他原因,其佈局是從導航欄下方開始到屏幕底部,高度爲ScreenHeight-64,64爲導航欄(44)+狀態欄(20)高度

四、navigationBar與navigationItem

1、navigationbar繼承自UIView,通常是位於屏幕頂端的控件。

2、navigationbar是navigationitem的容器,以stack的形式管理UINavigationitem。需要說明的是UInavigationbar屬於導航控制器,且只有一個,navigationitem是獨立存在的不屬於導航控制器也不屬於導航條,它是視圖控制器的屬性,每一個viewController都有一個navigationitem。navigationbar提供了多種方法來管理單個和多個navitionItem。

3、UINavigationitem也是容器。包括titleView 、左側N個UIBarButtonItem,右側N個UIBarButtonItem這些控件,並提供了方法來管理這些控件。

總結 , navigationBar與navigationItem關係 ,  可以類比 navigationController 與 viewcontroller, 
navigationItem 與 titleView , leftBarButtonItem 的關係, 可以類比 self.view 與 view上的子控件 .

NSLog(@"topItem  %@",self.navigationController.navigationBar.topItem);
NSLog(@"items  %@",self.navigationController.navigationBar.items);

topItem  <UINavigationItem: 0x102865e80> title='訂單詳情' leftBarButtonItems=0x2803a00f0
items  [
	第0個 -- <UINavigationItem: 0x102808640> title='熱門' titleView=0x101f4d400 
	第1個 -- <UINavigationItem: 0x1028ccb00> title='項目訂單' leftBarButtonItems=0x2803aa430 
	第2個 -- <UINavigationItem: 0x102865e80> title='訂單詳情' leftBarButtonItems=0x2803a00f0

https://www.jianshu.com/p/a7d5078e31db

 

發佈了91 篇原創文章 · 獲贊 31 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章