0.UINavigationController
-
UINavigationController,通过维护一个栈,来实现不同控制器之间的切换.每一个navigatinController对象都拥有一个viewControllers属性,是一个NSArray.最上面的叫topViewController,最下面的叫bottomViewController
-
层级结构:最底层是NavigationBar,再上是Custum Content,最上面是Navigation ToolBar(toolBar默认为nil,一般不会在页面上显示)
-
设置全局的navigationItem和toolBar的属性(apperance),由navigationController对象来设置,而具体到每个viewController中如何显示navigationItem和toolBar,则由viewController对象来设定.
-
navigationController是通过push和pop来控制界面之间的跳转的
-
一般初始化的时候指定rootViewController,initWithRootViewController.
-
导航控制器的共性设置可在自定的导航控制器类中的+initialize中实现,因为该方法只在类创建的时候执行一次,在导航控制器类中获取导航条用apperance: - UINavigationBar *navBar = [UINavigationBar appearanceWhenContaineInInstancesOfClasses:@[self]]; //这里的self是类
-
要想改变每个导航控制器的返回按钮为统一样式,可以用自定义导航控制器,然后重写push方法,拦截每个push操作,然后在这个里面可以拿到push的目标控制器,修改其backBarButtonItem即可.
1.NavigationItem:
-
1.是UIViewController的一个属性,每一个加到NavigationCotroller的ViewController都会有一个对应的NavigationItem
-
2.NavigationItem由viewController以懒加载的形式创建,所以我们使用的时候一定要在确认它已经被创建之后使用.
-
3.可设置leftBarButtonItem,rightBarButtonItm,backBarButtonItem,title,titleView以及prompt属性.
-
2.titleTextAttributes:
设置导航栏title的颜色,字体
NSMutableDictionary *titleAttr = [NSMutableDictionary dictionary];
titleAttr[NSForegroundColorAttributeName] = [UIColor whiteColor];
titleAttr[NSFontAttributeName] = [UIFont boldSystemFontOfSize:20];
[bar setTitleTextAttributes:titleAttr];
3.NavigationBar:
-
1.通过navigationController去获取,self.navigationController.navigationBar
-
2.设置导航栏两侧的按钮的文字的颜色, [self.navigationController.navigationBar setTintColor];
-
3.navigationBar 的显示原则:
-
left side of the navigationBar
-
如果当前的viewController设置了leftBarButtonItem,则显示当前VC设定的leftBarButtonItem
-
如果当前VC没有设置leftBarButtonItem,且当前VC不是rootVC的时候,则显示前一层VC的backBarButtonItem.如果前一层的VC没有显示的指定backBarButtonItem,系统会根据前一层VC的title属性自动生成一个back按钮,并显示出来.
-
如果当前的VC没有设置leftBarButtonItem,且当前VC已经是rootVC时,左边将不显示任何东西
-
-
right side of the navigationBar
-
如果当前VC指定了rightBarButtonItem,则显示指定内容
-
如果当前VC没有指定rightBaruttonItem,则不显示任何内容
-
-
title 也就是中间部分
-
如果当前VC通过navigationItem.titleView指定了自定义的titleView,,系统将会显示这个titleView,注意titleView的高度不要超过navigationBar的高度
-
如果当前VC没有指定titleView,系统将会根据当前VC的title或者当前VC的navigationItem.title的内容创建一个Label并显示.优先显示navigationItem.title.
-
-
4.ToolBar
-
1.toolBar是navigationController自带的属性,但默认情况下隐藏,可以通过设置 self.navigationController.toolBarHidden = NO; 来让工具栏显示出来.
-
2.工具栏中的内容,可以设置 当前VC的toolBarItems属性来设置,赋值给它的数组中的每个元素必须是UIBarButtonItem对象
5.NavigationControllerDelegate
主要就是willShow和didShow两个方法.
6.开启导航条的全屏滑动功能
导航控制器自带的有侧滑返回功能,这里做个扩展,将它设为全屏可滑动返回
//禁止系统的滑动交互手势
self.interactivePopGestureRecognizer.enabled = NO;
//添加自定义的手势 使用系统的target和action
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
//设置手势代理,是为了在其代理方法里面判断是否 禁止手势
pan.delegate = self;
//添加自定义手势
[self.view addGestureRecognizer:pan];
/*********************下面是手势的代理方法****************************/
//需要利用手势的代理方法来选择是否禁止手势,需要在合适的地方禁止手势滑动,也就是在根控制器里面禁止.否则会有bug
//该方法与下面的方法效果类似,实验表明都可用
//- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
//
// NSLog(@"should Begin");
// return (self.viewControllers.count >1);
// }
//该方法只要拖动就会进来
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
// NSLog(@"********");
return (self.viewControllers.count >1);
}
7.隐藏底部工具条的实现方法
拦截系统的push,pop操作,也就是重写push,pop的方法,可以在这里面统一设置隐藏底部工具条.
纯代码写的时候需要判断当前控制器是否是跟控制器,也就是做到根控制器的时候不隐藏
if(self.viewControllers.count){//如果当前控制器不是跟控制器
//这里的self 指的是navigationControlle
//不等于0 表示当前非跟控制器
//隐藏底部工具条
viewController.hidesBottomBarWhenPushed = YES;
}
8.如果想要给某个界面自定义navigationBar,可以在先用导航控制器的对象获取当前的栈顶控制器,然后判断该栈顶控制器是否是我们需要修改的那个控制器,如果是就修改
//如果当前导航控制器的栈顶控制器是需要修改的控制器的时候,重新设置navigationBar
if ([self.topViewController isKindOfClass:[WZHArenaViewController class]]) {
[self.navigationBar setBackgroundImage:[UIImage imageNamed:@"NLArenaNavBar64"] forBarMetrics:UIBarMetricsDefault];
}
如何判断当前viewController是push还是present的方式显示的
NSArray *viewcontrollers=self.navigationController.viewControllers;
if (viewcontrollers.count>1) {
if ([viewcontrollers objectAtIndex:viewcontrollers.count-1]==self) {
//push方式
[self.navigationController popViewControllerAnimated:YES];
}
}
else{
//present方式
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
-
通过present出来的viewController不会存入到self.navigationController.childViewControllers数组中,而通过push方式显示的viewController会保存在该数组的最后.
-
根据上述的情况,那怎么判断当前控制器是否是根控制器呢,可以根据self.navigationController.childViewContrlllers.count来判断,只要该数不等于0,就表明不是根控制器.