导航控制器
- 导航控制器基础
- 基本概念
- 具体使用
- 导航控制器切换
- 演示
- 具体使用
- 注意
- 导航栏与工具栏
- 基本概念
- 具体使用:
- 总结
导航控制器基础
基本概念
- 根视图控制器(Root View Controller):导航控制器的第一个视图控制器,通常是应用程序的主屏幕。
- 导航栏(Navigation Bar):用于显示当前视图控制器的标题以及在导航栈中的位置。
- 工具栏(Toolbar):可选的,用于显示当前视图控制器的工具按钮。
- 返回按钮(BackButton):用于在导航栏中返回上一个视图控制器。
下图是一个导航栏的组成。
具体使用
首先我们要创建一个根视图控制器,该类继承UIViewController。
然后我们在SceneDelegate.m中我们创建一个根视图控制器对象和导航控制器对象。
#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {self.window.frame = [UIScreen mainScreen].bounds;//创建一个根视图控制器VCRoot *root = [[VCRoot alloc] init];//创建导航控制器//导航控制器主要用来管理多个视图控制器的切换//层级的方式来管理多个视图控制器//创建控制器时,一定要有一个根视图控制器UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController: root];root.view.backgroundColor = [UIColor blueColor];//将windows的根视图设置为导航控制器self.window.rootViewController = nav;[self.window makeKeyAndVisible];
}
随后,我们在我们创建的根视图控制器的实现接口中,完成对导航栏属性的学习。
- UIBarButtonItem:是 iOS 中用于创建和管理导航栏、工具栏等界面元素的类。
该类有三种初始化方法,一个是自定义文本,一个是使用系统风格,一个是将其他类型的控件作为按钮。 self.title = @"根视图"与 self.navigationItem.title = @"Title";
:这两个都是设置导航栏标题的属性,navigationItem.title的优先级高于title
#import "VCRoot.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor yellowColor];//设置导航栏的标题文字self.title = @"根视图";//上下都是设置title//如果没有设置navigationItem.title,为nil,//系统则会使用self。title作为标题。//优先下,再看上,如无下,则将上赋值给下//设置导航元素项目的标题self.navigationItem.title = @"Title";//创建一个导航栏左侧的按钮//根据title文字来创建按钮//P1:按钮上的文字//P2:按钮风格//P3:事件拥有者//P4:按钮事件//Bar专门用在导航栏上的按钮UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithTitle:@"左侧" style:UIBarButtonItemStyleDone target:self action:@selector(pressLeft)];//导航元素项的左侧按钮赋值self.navigationItem.leftBarButtonItem = leftBtn;//创建一个导航栏左侧的按钮//根据系统风格创建按钮//P1:按钮上的文字//P2:按钮风格//P3:事件拥有者//只需要指定风格样式,系统风格的按钮内容或标题文字不能改变UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(pressRight)];UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 50, 40)] ;label.text = @"test";label.textAlignment = NSTextAlignmentCenter;//将任何类型的控件添加到导航按钮的方法UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithCustomView:label] ;//添加多个按钮,创建按钮数组NSArray *arrayBtn = [NSArray arrayWithObjects:rightBtn,item3, nil ];UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(press:)];[label addGestureRecognizer:tap];label.userInteractionEnabled = YES;self.navigationItem.rightBarButtonItems = arrayBtn;
}-(void)press: (UITapGestureRecognizer*)tap {NSLog(@"press");
}
-(void) pressLeft
{NSLog(@"左侧按钮被按下!");
}-(void) pressRight
{NSLog(@"右侧按钮被按下!");
}@end
效果:
导航控制器切换
演示
下图为通过点击切换了不同的视图,而我们通过导航控制器也可以实现这一需求。
具体使用
首先我们创建三个视图控制器。
然后,与上面所学相同,我们需要在SceneDelegate.m中我们创建一个根视图控制器对象和导航控制器对象。
#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {self.window.frame = [UIScreen mainScreen].bounds;VCRoot *root = [[VCRoot alloc] init];UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root];self.window.rootViewController = nav;[self.window makeKeyAndVisible];}
接着,我们在根视图中使用导航栏进行下一级视图控制器的推出。
首先学习translucent
属性,该属性用于控制视图控制器是否透明,默认为YES,透明的。
不透明效果:
我们通过创建一个按钮,在响应事件中添加pushViewController: animated:
方法,来实现下一个视图的推出。注意,需要新建下一级视图控制器
#import "VCRoot.h"
#import "VCSecond.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {[super viewDidLoad];//设置导航栏的透明度//默认透明度为YES,可透明的。//NO为不透明。self.navigationController.navigationBar.translucent = YES;self.navigationController.navigationBar.barStyle = UIBarStyleDefault;self.view.backgroundColor = [UIColor whiteColor];self.title = @"根视图";UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithTitle:@"下一级" style:UIBarButtonItemStylePlain target:self action:@selector(pressNext)];self.navigationItem.rightBarButtonItem = next;
}-(void) pressNext
{//创建新的视图控制器VCSecond* vcSecond = [[VCSecond alloc] init];//使用当前视图控制器的导航控制器对象,推出vcSecond控制器//参二为是否需要添加动画效果[self.navigationController pushViewController:vcSecond animated:YES];
}@end
同样的,我们在二级视图中用相同的方法推出第三级视图
#import "VCSecond.h"
#import "VCThired.h"
@interface VCSecond ()@end@implementation VCSecond- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor greenColor];self.title = @"儿子视图";UIBarButtonItem *btnNext = [[UIBarButtonItem alloc] initWithTitle:@"第三级" style:UIBarButtonItemStylePlain target:self action:@selector(pressNext)];self.navigationItem.rightBarButtonItem = btnNext;
}-(void) pressNext
{VCThired *vc = [[VCThired alloc] init];[self.navigationController pushViewController:vc animated:YES];
}
我们在第三级中,自己设定左侧按钮,此时会发现自己设定的按钮样式会覆盖系统的按钮样式。
当迭代到第三级后,我们想直接返回到根视图时,可以使用popToRootViewControllerAnimated
方法作为响应事件,直接返回到根视图。
#import "VCThired.h"@interface VCThired ()@end@implementation VCThired- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.title = @"孙子视图";UIBarButtonItem *btnLeft = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(pressBack)];UIBarButtonItem *btnRight = [[UIBarButtonItem alloc] initWithTitle:@"返回根视图" style:UIBarButtonItemStylePlain target:self action:@selector(pressRight)];//当自己设定左侧按钮时//返回按钮会被左侧按钮替换self.navigationItem.leftBarButtonItem = btnLeft;self.view.backgroundColor = [UIColor blueColor];self.navigationItem.rightBarButtonItem = btnRight;
}-(void) pressRight
{[self.navigationController popToRootViewControllerAnimated:YES];
}-(void) pressBack
{//将当前的视图控制器弹出,返回上一级界面[self.navigationController popViewControllerAnimated:YES];
}@end
效果展示:
注意
在每一个视图中,我们进行视图的推出和返回时,都对self.navigationController
对象进行。那这个self.navigationController对象是不同的三个对象呢,还是同一个对象?
实际上,三个不同视图中的self.navigationController对象都是同一个对象。
这与导航控制器推出视图控制器的方式有关:通过 [self.navigationController pushViewController:vc animated:YES]
方法将视图控制器 vc 推入导航堆栈时,vc 成为导航堆栈的最顶层视图控制器,但导航控制器对象本身并没有改变。
因此:我们每次看到的视图就是导航堆栈的栈顶,使用push是将视图控制器推入栈顶,使用pop是将视图控制器推出栈顶。
而因为导航控制器对象本身是没有改变的,所以我们设置了根视图的导航控制器,就设置了所有视图的导航控制器
导航栏与工具栏
基本概念
导航栏前面已经介绍了,我们在此着重介绍工具栏。
工具栏的组件:
- 固定空间按钮(Fixed Space Bar Button):固定空间按钮是另一种特殊类型的工具栏按钮,用于创建固定宽度的间距。它可以用于调整按钮之间的间距或在工具栏上创建对齐效果。
- 标签(Label):用于显示相关的信息或标题,提供上下文或描述工具栏中的操作。
- 图片视图(Image View):用于显示图标、图像或其他视觉元素。图像视图可以代表特定的操作或提供视觉上的识别。
- 自定义视图(Custom View):自定义的视图元素,自定义视图可以是任何 UIView 的子类,允许你在工具栏上添加自定义的界面元素,如文本输入框、开关按钮等。
工具栏的基本元素:
- 工具栏按钮(Toolbar Button):工具栏中的单个按钮,可以通过点击来执行特定操作或导航到其他屏幕。
- 工具栏项(ToolbarItem):工具栏中的一个单独元素,可以包含一个或多个工具栏按钮。
- 工具栏控制器(ToolbarController):用于管理工具栏的视图控制器,可以使用工具栏控制器来添加、删除和重新排列工具栏项。
- 工具栏样式(ToolbarStyle):工具栏的外观样式,可以通过设置工具栏的颜色、透明度、背景图像和按钮样式等属性来自定义工具栏的外观。
具体使用:
导航栏的创建在此不再赘述,我们直接进入学习
隐藏导航栏的两个方法:
//该属性默认为NOself.navigationController.navigationBar.hidden = NO;self.navigationController.navigationBarHidden = NO;
在iOS13之后,我们使用UIBarAppearance类设置导航控制器的外观样式
//UIBarAppearance是iOS13后推出的一个对相应空间设置外观样式的类,可以统一配置NavigationBar、TabBar、ToolBar等的外观样式//UINavigationBarAppearance可以设置导航栏对象的外观样式//创建一个UINavigationBarAppearance对象UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];//背景颜色appearance.backgroundColor = [UIColor whiteColor];//阴影appearance.shadowImage = [[UIImage alloc] init];appearance.shadowColor = nil;self.navigationController.navigationBar.scrollEdgeAppearance = appearance;
接着,我们将默认为隐藏的工具栏开启,并且设置三个不同的按钮来演示工具栏按钮的使用。
此处与导航控制器一样,我们分别采用三种初始化方法,来实现文本,系统风格,和自定义图像的初始化。
与导航控制器不同的是,此处我们额外使用固定空间按钮或者弹簧按钮,实现将工具栏的按钮以相同间距排列。
//显示工具栏对象//默认工具栏是隐藏的self.navigationController.toolbarHidden = NO;self.navigationController.toolbar.translucent = NO;//创建三个工具栏按钮UIBarButtonItem *btn1 = [[UIBarButtonItem alloc] initWithTitle:@"left" style:UIBarButtonItemStylePlain target:nil action:nil];UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(pressNext)];UIButton *btnImage = [UIButton buttonWithType:UIButtonTypeCustom];[btnImage setImage:[UIImage imageNamed:@"7_.jpg"] forState:UIControlStateNormal];btnImage.frame = CGRectMake(0, 0, 60, 60);UIBarButtonItem *btn3 = [[UIBarButtonItem alloc] initWithCustomView:btnImage];//位置分开//法一:固定控件按钮
// UIBarButtonItem *btnF1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
//
// btnF1.width = 100;//法二://创建自动计算按钮,弹簧按钮UIBarButtonItem *btnF2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];//按钮数组的创建NSArray *arrayBtns = [NSArray arrayWithObjects:btn1, btnF2, btn2, btnF2, btn3, nil];self.toolbarItems = arrayBtns;}- (void) pressNext
{ //使用此按钮弹出下一视图。VCSecend *vc = [[VCSecend alloc] init];[self.navigationController pushViewController:vc animated:YES];}- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setToolbarHidden:NO animated:animated];
}
效果:
点击照相机后:
在上面的效果中,当进入第二个视图我们的工具栏消失了,使用如下代码实现:
在根视图中加入:
- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setToolbarHidden:NO animated:animated];
}
在二视图中加入:
- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setToolbarHidden:YES animated:animated];
}
即可实现。
总结
导航控制器是UI学习的重要一部分,经过这篇总结融会贯通,我觉得我又行咯。