1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > NavigationController

NavigationController

时间:2018-08-30 19:07:39

相关推荐

NavigationController

实际开发中都是多控制器的;用一个控制器(父)管理多个控制器(子)

ios提供2个特殊的(父)控制器

UINavigationControler
简介

导航控制器,可以轻松完成多个控制器之间的切换,其结构包含导航条(y=20)、栈顶控制器的view、导航控制器的view。导航控制器需要设置一个根控制器,一般是UIViewControler。基本使用

最开始的时候,栈顶控制器的view就是导航控制器的根控制器的view。

1.先去掉Info.plist的倒数第三行的main,以采用代码方式创建

2.在AppDelegate.m中:

其中,先创建窗口,再创建导航控制器(同时创建了一个UIviewControler的控制器,作为其根控制器),然后把该窗口的根控制器设为所创建的导航控制器,最后显示窗口。

PS:一般地,导航控制器的根控制器来自新建一个UIViewControler类,然后import进来。另外,只要一个控制器是导航控制器的子控制器,那么导航控制器就会成为这个控制器的一个属性(可以拿到 )

控制器之间的跳转:

根控制器的导航控制器调用pushViewControler方法,参数为跳转后的控制器。跳转后,显示的是后来这个ViewControler的view,也成了栈顶控制器的view,同时从window上移除了前一个控制器的view,但仍保存于导航控制器的子控制器数组中。

PS:导航控制器是其根控制器的一个属性。

导航控制器的子控制器

一般保存在数组(以栈的形式)(先进后出)中

PS:使用setViewControllers方法可以一次压入多个控制器,但是只会显示最后压入的那个控制器的view(栈顶控制器)

[nav setViewControllers:@[vc1,vc2,vc3] animated:YES];

获取栈顶控制器:navController.topViewController

获取当前可见视图的控制器:.visibleViewController

控制器的返回

是跳转操作的逆向。执行返回操作后,先从window中移除当前控制器的view,同时把该控制器(在栈顶)从栈中移除。此时在栈顶的控制器的view会添加到window,显示出来,从而实现返回。

注意:

要回到指定的控制器,这个指定的控制器必须得是导航控制器的子控制器。

当一个控制器被pop后,控制器内存就被释放了(会调用deinit/dealloc函数。

控制器被销毁,它的view不一定就销毁(只要有storng指针),但是当一个控制器被销毁,那么它的view的业务逻辑无法处理。

设置导航条的内容

由栈顶控制器的navigationItem属性来决定导航条的内容,在栈顶控制器的.m的viewDidLoad{ }中设置

其中,titleView可以设为各种控件

设置navBar的字体大小,颜色

[nav.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:19],NSForegroundColorAttributeName:[UIColor whiteColor]}];navBar的隐藏状态:navController.navigationBarHidden = YES;

UINavigationBar通过UINavigationItem堆栈,按照如下方式来决定展示在UINavigationBar中的内容

位于中间的标题会根据下方顺序选择展示的内容:

如果topItem设置了标题视图(titleView属性), 则展示标题视图

如果topItem设置了标题文字(title属性), 则展示标题文字

如果以上都未设置, 则展示空白。位于右侧的按钮会根据下方顺序选择展示的内容:

如topItem设置了右侧按钮(rightBarButtonItem属性)则展示右侧按钮

如果以上都未设置, 则展示空白。位于左侧的按钮会根据下方顺序选择展示的内容:

如topItem设置了左侧按钮(leftBarButtonItem属性), 则展示左侧按钮

如backItem设置了返回按钮(backBarButtonItem), 则展示返回按钮

如backItem设置了标题(title), 则展示用标题文字封装的返回按钮如果以上都未设置, 则展示利用文字"Back"封装的返回按钮。

设置导航条的外观

UINavigationBar类中提供了大量属性/方法用于设置其外观, 我们可以设置其样式、背景颜色、色彩颜色、文字属性,同样, 我们也可以设置其背景图片、阴影图片。

样式:navigationBar.barStyle

该属性可为UIBarStyleDefault(白底黑字)、UIBarStyleBlack(黑底白字)背景色:navigationBar.barTintColor前景色:navigationBar.tintColor设置背景图片:[navigationBar setBackgroundImage:。。。];阴影图片:navigationBar.shadowImage = [UIImage imageNamed:@""];

区分关系:

NavigaitonBar是导航栏,位于屏幕上方,管理整个导航控制器的navigationItem,它类似navigationcontroller一样,提供了一个栈来管理UINavigationItem。在编程时,一般只设置每个控制器的navigationItem属性。

一个导航控制器管理多个视图控制器(多个视图控制器共享一个导航控制器),而一个导航控制器只有一个UINavigationBar,被管理的多个视图控制器共享这一个UINavigationBar,只要一个视图控制器改变了UINavigationBar的属性则影响是全局的。

每个视图控制器都会有属于自己的UINavigationItem,系统会以懒加载的方式创建一个UINavigationItem显示在UINavigationBar中,改变UINavigationItem只会在当前控制器起作用,不会影响其它控制器。

通过storybord跳转控制器

设根控制器为导航控制器(删掉默认的控制器,拖入nav,设之为默认即添加箭头,添加导航控制器的根控制器(viewcontroler),方法是采用拖线的方式,点击rootcontroler;再拖入一个viewcontroler,实现控制器之间的跳转,方法是拖线(从一个按钮拖到下一个控制器,点击show选项)

设置导航条的内容(可以把其他控件如item等拖到导航条;可以设导航条标题;

自定义导航控制器

设置导航条统一的样式

+(void)initialize{// 获取APP的导航条标识 // UINavigationBar *bar = [UINavigationBar appearance]; //这种写法有bug,它会代表app中所有的导航条,当app中还有自定义导航条时也会被包含UINavigationBar *bar = [UINavigationBar appearanceWhenContainedIn:[PDNavigationViewController class],nil]; //(获取指定某几个类的导航条标识)//设置nav bar的背景图片(因无法设置背景颜色)[bar setBackgroundImage:[UIImage imageNamed:@"navBar"] forBarMetrics:UIBarMetricsDefault]; //标题字体大小、颜色NSMutableDictionary *dict = [NSMutableDictionary dictionary];dict[NSFontAttributeName] = [UIFont systemFontOfSize:22.0]; dict[NSForegroundColorAttributeName] = [UIColor whiteColor]; [bar setTitleTextAttributes:dict];}

统一样式只需设一次即可。因此,在initialize方法中设置,此方法当当前类第一次初始化的时候才调用,这样就实现只设置一次。当然在加载时viewDidLoad方法也只调用一次,但是一个缺点就是,当要创建多个导航控制器时,会调用(设置)多次。

设置统一的返回按钮

重写push方法来实现

-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{[super pushViewController:viewController animated:animated];//判断当前不是在根控制器下,此时设置leftBarButtonItemif(self.viewControllers.count > 1) viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"nearby"] style:0 target:self action:@selector(back)];}-(void)back{[self popViewControllerAnimated:YES]; //pop返回上层}

(此时就系统没有了滑动返回功能)

恢复滑动返回功能

原理:通过清空代理的方式可以恢复

self.interactivePopGestureRecognizer.delegate = nil;

但是存在bug,因为清空之后会带来后续影响,改善如下:

@interface PDNavigationViewController ()<UINavigationControllerDelegate>@property(nonatomic,strong) id popGesture; //用于暂存@end-(void)viewDidLoad {[super viewDidLoad];self.popGesture = self.interactivePopGestureRecognizer.delegate; //暂存代理self.delegate = self; //将代理设为自身}

在导航控制器代理方法中清空代理,此方法当控制器显示完毕时调用,因此能够拿到当前的控制器

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{//根控制器中不需滑动返回,此时还原代理if(self.viewControllers[0] == viewController){ //当前是根控制器时self.interactivePopGestureRecognizer.delegate = self.popGesture; //还原代理}else{ //非根控制器时,清空代理( 恢复滑动返回功能 )self.interactivePopGestureRecognizer.delegate = nil; }}

实现全屏滑动返回( 系统默认从左侧滑动才能返回 )

-(void)viewDidLoad {[super viewDidLoad];//以下代码实现全屏滑动返回id target = self.interactivePopGestureRecognizer.delegate;self.interactivePopGestureRecognizer.enabled = NO;UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];[self.view addGestureRecognizer:pan];pan.delegate = self;}

解决全屏滑动的bug

//当开始滑动就会调用-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{//如果是在非根控制器,才允许滑动BOOL open = self.viewControllers.count > 1; return open;}

作者: Arthur凌

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。