一、概述
- 類繼承關(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ù):
- 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)的.
若自定義了返回按鈕,又想"右滑返回的手勢有效"的解決辦法:
- 方法一:在視圖基類中自定義手勢返回,但是沒有系統(tǒng)的漸變的效果.博主不推薦使用該方法.
- 網(wǎng)上查的解決辦法是:UINavigationController返回手勢失效問題
在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)的屬性和方法:
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é):寫的很詳細.