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

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)