您的位置:首页 > 产品设计 > UI/UE

UINavigationController 及使用中遇到的问题总结

2016-04-26 00:45 316 查看

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,就表明不是根控制器.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OC UI UINavagationControll