iOS-UINavigationController官方文檔分析大總結(jié)

一、概述

  • 類繼承關(guān)系如下:UINavigationController
    <- UIViewcontroller <- UIResponder <- NSObject
    .
  • 它是一個容器類視圖控制器,以棧的形式管理一組視圖控制器,位于棧底的視圖是其rootViewController,管理視圖控制器個數(shù)理論上不受限制(實際受內(nèi)存限制),push和pop方法來彈入彈出控制器,最多只能顯示一個視圖控制器,那就是處于棧頂?shù)囊晥D控制器.
  • 如果不給它添加視圖控制器也不會報錯,界面上也有視圖,因為UINavigationController繼承自UIViewController,也有自己的view,只不過默認情況下.view.backgroundColor為nil,即透明的。
  • 若不給除根視圖控制器之外的其他視圖控制器設(shè)置返回按鈕,UINavigationController會給他們設(shè)置返回按鈕(<返回).
  • UINavigationController管理的對象有:UINavigationBar,UIToolBar.UIToolBar默認是隱藏的.
  • UINavigationController允許開發(fā)者自定義UINavigationBar外觀相關(guān)的屬性,但是其frame bounds alpha不允許直接自定義,除非使用UINavigationBar的子類,
    初始化UINavigationController時,方法為:
    initWithNavigationBarClass:toolbarClass:
  • 自定義UINavigationBar,可使用 UIAppearance,該API是全局修改,常在APPDelegate方法里面使用,比如全局設(shè)置標題的字體大小 顏色等.

二、常用函數(shù)

初始化函數(shù):

- initWithRootViewController:

- initWithNavigationBarClass:toolbarClass:

跟導航欄相關(guān)的函數(shù)和屬性

使用push方法能將某個控制器壓入棧

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;

使用setViewControllers一次壓入多個控制器vc1->vc2->vc3,會顯示最后的控制器vc3(處于棧頂),代碼如下:

UINavigationController *nav = [[UINavigationController alloc] init];
window.rootViewController = nav;// 創(chuàng)建3個測試控制器UIViewController *vc1 = [[UIViewController alloc] init];
vc1.view.backgroundColor = [UIColor blueColor];
UIViewController *vc2 = [[UIViewController alloc] init];
vc2.view.backgroundColor = [UIColor redColor];
UIViewController *vc3 = [[UIViewController alloc] init];
vc3.view.backgroundColor = [UIColor greenColor];// 最終會顯示vc3[nav setViewControllers:@[vc1,vc2,vc3] animated:YES];

使用pop方法可以移除棧頂控制器當一個控制器被pop后,控制器內(nèi)存就被釋放了(會調(diào)用deinit/dealloc函數(shù)):

- (UIViewController *)popViewControllerAnimated:(BOOL)animated;

一層一層的返回不方便,可以直接回到指定的控制器VC_A(處與VC_A與棧頂之間的控制器全被釋放),下面代碼執(zhí)行后,VC_A處于棧頂:

- (NSArray *)popToViewController:VC_A animated:(BOOL)animated;

回到根控制器(棧底控制器):

-(NSArray *)popToRootViewControllerAnimated:(BOOL)animated;

獲取被管理的控制器

/// 當前管理的所有的控制器
@property(nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers;/// 棧頂控制器
@property(nullable, nonatomic,readonly,strong) UIViewController *topViewController;
/// 當前可見的VC,可能是topViewController,也可能是當前topViewController present(modal)出來的VC,總而言之就是可見的VC
@property(nullable, nonatomic,readonly,strong) UIViewController *visibleViewController;

注意,topViewController與visibleViewController大部分情況一樣,也有可能不同

NavigationBar不常用屬性卻非常有用的屬性

interactivePopGestureRecognizer

關(guān)于這個屬性的小結(jié):

  • 注意:從iOS7開始,系統(tǒng)為UINavigationController提供了一個interactivePopGestureRecognizer用于右滑返回(pop),但是,如果自定了back button或者隱藏了navigationBar,該手勢就失效了。

  • 所以如果若想使用這個功能,則返回按鈕最好使用系統(tǒng)的.

若自定義了返回按鈕,又想"右滑返回的手勢有效"的解決辦法:

在UINavigationController基類中添加代碼如下:

遵守協(xié)議是 <UIGestureRecognizerDelegate>

切記:使用此方法時  self.hidesBarsOnSwipe = YES;不能使用,即默認是關(guān)閉的,否則會造成沖突,在右滑返回時 會出現(xiàn)navigationBar不正常顯示的問題,如有興趣可自己嘗試一下.
- (void)viewDidLoad {
    [super viewDidLoad];
//    self.hidesBarsOnSwipe = YES;
//    self.toolbarHidden = NO;
    self.hidesBottomBarWhenPushed = YES;
    self.interactivePopGestureRecognizer.delegate =  self;

}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (self.viewControllers.count <= 1 ) {
        return NO;
    }
    
    return YES;
}
  • 關(guān)于右滑返回的總結(jié)是:若想使用該屬性,則最好使用系統(tǒng)返回鍵.

下面這些屬性在某些情況下會使用到

  • 在小屏4s 5s上有些PM可能會要求在瀏覽內(nèi)容時隱藏導航欄,這個時候就可使用此屬性.

hidesBarsOnTap(點擊隱藏導航欄,再點擊顯現(xiàn),皆有向上/下過度的過程)
hidesBarsOnSwipe(經(jīng)試驗是向上輕掃隱藏,向下輕掃則顯現(xiàn),皆有向上/下過度的過程)
hidesBarsWhenVerticallyCompact
hidesBarsWhenKeyboardAppears
navigationBarHidden
barHideOnTapGestureRecognizer
barHideOnSwipeGestureRecognizer

ToolBar屬性

- setToolbarHidden:animated:
toolbarHidden

三、導航條

UINavigationController是做導航用的,具體的操作大部是由導航條來完成,導航條的使用就顯得很重要。導航條的內(nèi)容由控制器的navigationItem屬性決定。
1 navigationItem的屬性
一般使用self.navigationItem.對應(yīng)屬性來獲取屬性,或者設(shè)置屬性。或者使用self.navigationController獲取到navigationController,再通過navigationController獲取到想要設(shè)置的viewController

中間的標題文字

@property(nullable, nonatomic,copy) NSString *title;

中間標題視圖

@property(nullable, nonatomic,strong) UIView *titleView;

項目中的常用方法是:

UIImageView *titleView = [[UIImageView alloc]initWithFrame:CGRectMake(SCREEN_WIDTH/2 - 100, 0, 200, 44)];
titleView.image = 圖片.
[self.navigationItem.titleView addSubview:titleView];

導航欄附加解釋說明,如果設(shè)置了此字段,導航欄會高出30個點顯示此字段在title正上方
@property(nullable,nonatomic,copy) NSString *prompt;
prompt顯示位置


自定義左上角的返回按鈕

/// 直接設(shè)置
@property(nullable, nonatomic,strong) UIBarButtonItem *leftBarButtonItem;

大部分情況下,我們需要指定左邊返回按鈕距離左邊框的距離,可以如下設(shè)定:

//自己項目中的方法
 UIButton *backBt = [UIButton buttonWithType:UIButtonTypeSystem];
 backBt.frame = CGRectMake(0, 0, LabelWidth_20, LabelWidth_20);
 [backBt setBackgroundImage:[UIImage imageNamed:@"回退"] forState:UIControlStateNormal];
 [backBt addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
 self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:backBt];
//系統(tǒng)推薦方法如下
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"gobackItem.png"] style:UIBarButtonItemStylePlain target:self action:@selector(backViewcontroller)];
UIBarButtonItem *fixedItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
// 設(shè)置邊框距離,個人習慣設(shè)為-16,可以根據(jù)需要調(diào)節(jié)fixedItem.width = -16;
self.navigationItem.leftBarButtonItems = @[fixedItem, leftItem];

下圖為設(shè)置邊框距離前后的差別:

沒有設(shè)置邊框距離


設(shè)置邊框距離后


忽略點:(關(guān)于系統(tǒng)返回按鈕)

  • 子導航條后退按鈕,假設(shè)通過VC1 push VC2,那么如果設(shè)置VC1.navigationItem.backBarButtonItem就會顯示在VC2的左上角返回按鈕;
    如果再設(shè)置VC2.navigationItem.leftBarButtonItem則會覆蓋VC1的設(shè)置;
    如果VC1和VC2都沒有設(shè)置,則會顯示默認的backBarButtonItem。
@property(nullable,nonatomic,strong) UIBarButtonItem *backBarButtonItem;
  • push到下一個頁面時,若不自定義返回按鈕,則會顯示默認的返回按鈕 "<返回" 字體顏色為系統(tǒng)字體顏色,即backBarButtonItem,且系統(tǒng)的向左平移pop的功能會自己實現(xiàn).
  • 若自定義了返回按鈕 則系統(tǒng)自帶的向左平移pop的功能會失效.
  • title的長度不可過長,否則會造成系統(tǒng)返回按鈕的 返回 字體消失,只剩余一個<

自定義右上角的按鈕,或多個按鈕

@property(nullable, nonatomic,strong) UIBarButtonItem *rightBarButtonItem;/// 一次設(shè)置多個按鈕
@property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *rightBarButtonItems;

2 設(shè)置navigationItem的字體格式

// 字體大小19,顏色為白色
[nav.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:19],NSForegroundColorAttributeName:[UIColor whiteColor]}];

四、UIToolBar
UINavigationController自帶了一個工具欄,通過[self.navigationController setToolbarHidden:NO];來顯示工具欄,工具欄中的內(nèi)容可以通過viewController的toolbarItems來設(shè)置,顯示的順序和設(shè)置的NSArray中存放的順序一致,每一個UIBarButtonItem對象都可以設(shè)定點擊事件,可以使用系統(tǒng)提供的很多常用風格的對象,也可以根據(jù)需求進行自定義,下面舉例使用系統(tǒng)提供的樣式。

// 1 顯示工具條
[self.navigationController setToolbarHidden:NO];
// 2 創(chuàng)建四個UIBarButtonItem
UIBarButtonItem *itemOne = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil];
UIBarButtonItem *itemTwo = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:nil action:nil];
UIBarButtonItem *itemThree = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil];
UIBarButtonItem *itemFour = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:nil action:nil];
// 間隙
UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
// 3 添加到toolbarItemsvc.
toolbarItems = @[itemOne,flexibleItem,itemTwo,flexibleItem,itemThree,flexibleItem,itemFour];

效果如下:


另外,UIToolBar使用的比較少,大部分情況下而是使用另一個導航控制器UITabBarController

五 UINavigationControllerDelegate

有兩個常用的方法

// 一般用于傳遞參數(shù),或者做一些其它處理
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

參考:http://www.cnblogs.com/mddblog/p/4556974.html

六 UINavigationBar、UINavigationItem、UIToolbar與UIBarButtonItem四者關(guān)系

補充:

1 三者概述

  • UITabBar 上展示的是: UITabBarItem( 其類繼承關(guān)系為--> UIBarItem --> NSObject)

  • UIToolBar 上展示的是: UIToolBarItem (其類繼承關(guān)系為-->UIBarButtonItem --> UIBarItem--> NSObject)

  • UINavigationBar 上展示的是: UINavigationItem(包括:titleView leftBarButtonItem leftBarButtonItems rightBarButtonItem rightBarButtonItems) (其類繼承關(guān)系為--> UIBarButtonItem --> UIBarItem--> NSObject)

2 三者區(qū)別

名稱 位置 作用 高度 appearance
UITabBar 任意位置(常見底部) 點擊前后item發(fā)生變化,管理一組視圖 49 全局修改UI
UIToolBar 任意位置(常見底部) 一般用作功能性點擊 44 全局修改UI
UINavigationBar 頂部 一般初始化UINavigationController時,自動生成UIUINavigationBar,也可以單獨使用 44 全局修改UI

NavigaitonBar
是導航欄,位于屏幕的上方,管理整個NavigationController的navigationItem,它類似navigationcontroller一樣提供了一個棧來管理UINavigationItem,在編程時,一般只設(shè)置每個控制器的navigationItem屬性.一個導航控制器管理多個視圖控制器(多個視圖控制器共享一個導航控制器),而一個導航控制器只有一個UINavigationBar,被管理的多個視圖控制器共享這一個UINavigationBar,只要一個視圖控制器改變了UINavigationBar的屬性則影響是全局的。每個視圖控制器都會有屬于自己的UINavigationItem,系統(tǒng)會以懶加載的方式創(chuàng)建一個UINavigationItem顯示在UINavigationBar中,改變UINavigationItem
只會在當前控制器起作用,不會影響其它控制器。

Toolbar
顯示在屏幕底部,是導航控制器的工具欄,一個導航控制器只有一個,在任何被管理的視圖控制器地方改變則會都改變。可以一次性添加多個UIBarButtonItem或按鈕(包裝成UIBarButtonItem后添加),有一個items數(shù)組屬性。

UIBarButtonItem
是UINavigationItem或者Toolbar具體的一個按鈕。

UITabBar外觀相關(guān)的屬性和方法:

自定義TabBar的方法參考:

barStyle
The tab bar style that specifies its appearance.

translucent
A Boolean value that indicates whether the tab bar is translucent.

barTintColor
The tint color to apply to the tab bar background.

itemPositioning
The positioning scheme for the tab bar items in the tab bar.

itemSpacing
The amount of space (in points) to use between tab bar items.

itemWidth
The width (in points) of tab bar items.

tintColor
The tint color to apply to the tab bar items.

backgroundImage
The custom background image for the tab bar.

shadowImage
The shadow image to use for the tab bar.

selectionIndicatorImage
The image to use for the selection indicator.

UINavigationBar外觀相關(guān)的屬性和方法:
backIndicatorImage
The image shown beside the back button.

backIndicatorTransitionMaskImage
The image used as a mask for content during push and pop transitions.

barStyle
The navigation bar style that specifies its appearance.

barTintColor
The tint color to apply to the navigation bar background.

shadowImage
The shadow image to be used for the navigation bar.

tintColor
The tint color to apply to the navigation items and bar button items.

translucent
A Boolean value indicating whether the navigation bar is translucent (YES
) or not (NO
).

- backgroundImageForBarMetrics:
Returns the background image for given bar metrics.

- setBackgroundImage:forBarMetrics:
Sets the background image for given bar metrics.

- backgroundImageForBarPosition:barMetrics:
Returns the background image to use for a given bar position and set of metrics.

- setBackgroundImage:forBarPosition:barMetrics:
Sets the background image to use for a given bar position and set of metrics.

- titleVerticalPositionAdjustmentForBarMetrics:
Returns the title’s vertical position adjustment for given bar metrics.

- setTitleVerticalPositionAdjustment:forBarMetrics:
Sets the title’s vertical position adjustment for given bar metrics.

titleTextAttributes
Display attributes for the bar’s title text.

UIToolBar外觀相關(guān)的屬性和方法:
barStyle
The toolbar style that specifies its appearance.

barTintColor
The tint color to apply to the toolbar background.

tintColor
The tint color to apply to the bar button items.

translucent
A Boolean value that indicates whether the toolbar is translucent (YES
) or not (NO
).

- backgroundImageForToolbarPosition:barMetrics:

- setBackgroundImage:forToolbarPosition:barMetrics:

- shadowImageForToolbarPosition:

- setShadowImage:forToolbarPosition:

關(guān)于詳細使用方法可參考:UINavigationBar 使用總結(jié):寫的很詳細.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內(nèi)容