UI基础 - UINavigationController:UINavigationBar | UIToolBar

■ UINavigationController

1. 导航控制器是专门管理具有层级关系内容的导航,以栈的方式管理所控制的视图控制器:至少要有一个被管理的视图控制器,这个被管理的视图控制器是导航控制器的根视图控制器

注:任何继承于 UIViewController 的控制器(包括多态)都可以作为导航控制器的根控制器

2. UINavigationController 是以栈的方式管理视图的,它所管理的视图被放进一个数组中。以下是通过导航控制器进入、返回视图的原理图

注:当底部视图控制器想要返回某一前面的视图控制器时,一定要从导航控制器中的子视图数组中获取

复制代码
// 错误做法
SecondViewController *secVC = [SecondViewController new];
[self.navigationController popToViewController:secVC animated:YES];

// 正确打开方式
// 根据子控制器的下标,返回指定页面
[self.navigationController popToViewController:(SecondViewController *)[self.navigationController.viewControllers  objectAtIndex:1] animated:YES];
// 返回上一级页面呢
[self.navigationController popViewControllerAnimated:YES];
// 返回起始页面:下标是 0 的页面
[self.navigationController popToRootViewControllerAnimated:YES];
复制代码

3. UINavigationController 的 view层 包含 3 个子视图:navigationBar、toolbar、contentView ,其中 contentView 不是属性,只是一种指代。我们可以通过遍历 view 的 subViews 来找到它

■ UINavigationBar

1. 导航条自 iOS 7 之后默认是透明的,iOS7 之前默认是不透明的:在透明情况下它会与 contentView 重合一部分区域;在不透明情况下 contentView 则会在它的下⾯

2. UINavigationBar 除了能定义⾃身的样式外,还管理了一组 UINavigationItem,它也是以栈的⽅式管理⼀组 Items,并提供有 push/pop 操作。UINavigationItem 属于 MVC 中的 M,封装了要显⽰在 UINavigationBar 上的数据:title、titleView、leftBarButtonItem 等

3. UINavigationItem 样式

4. 如何使用 UINavigationBar 

// - AppDelegate.m

复制代码
 1 #import "AppDelegate.h"
 2 #import "ViewController.h"
 3 @implementation AppDelegate
 4 
 5 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 6 
 7     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
 8     self.window.backgroundColor = [UIColor whiteColor];
 9     [self.window makeKeyAndVisible];
10 
11     ViewController *firstVC  =[[ViewController alloc] init];
12     firstVC.view.backgroundColor = [UIColor yellowColor];
13     firstVC.title = @"UINavigationController";
14     UINavigationController *rootVC = [[UINavigationController alloc] initWithRootViewController:firstVC];
15     // 毛玻璃效果:默认 YES
16     rootVC.navigationBar.translucent = NO;
17     rootVC.navigationBar.hidden = NO;
18 
19 
20     // 标题颜色、大小:如果设置背景图的话,会覆盖该效果
21     [rootVC.navigationBar setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
22                                                    [UIColor yellowColor],
23                                                    NSForegroundColorAttributeName,
24                                                    [UIFont systemFontOfSize:18],
25                                                    NSFontAttributeName,nil]];
26 
27     // iOS 13 之后,需使用 UINavigationBarAppearance
28     if(@available(iOS 13.0,*)){
29 
30         UINavigationBarAppearance *navBarAppearance = [[UINavigationBarAppearance alloc] init];
31         [navBarAppearance configureWithOpaqueBackground];
32         // 背景颜色
33         navBarAppearance.backgroundColor = [UIColor redColor];
34         // 背景图片:图片尺寸和 navigationBar尺寸 不相同的话,会自动填充
35         navBarAppearance.backgroundImage = [UIImage imageNamed:@"P150x20.png"];
36         navBarAppearance.backgroundImage = [UIImage imageNamed:@"P375x64.png"];
37 
38         // 重设标题颜色、大小
39         [navBarAppearance setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
40                                                    [UIColor greenColor],
41                                                    NSForegroundColorAttributeName,
42                                                    [UIFont systemFontOfSize:25],
43                                                    NSFontAttributeName,nil]];
44 
45         rootVC.navigationBar.standardAppearance = navBarAppearance;
46         rootVC.navigationBar.scrollEdgeAppearance = navBarAppearance;
47 
48     }
49     // iOS 13 之前配置背景颜色、背景图片
50     else{
51         // 背景颜色
52         rootVC.navigationBar.barTintColor = [UIColor redColor];
53         // 背景图片:不会自动填充
54         // 状况一:不同 navigationBar系统尺寸 保持一致的图片,效果展示会存在问题
55         [rootVC.navigationBar setBackgroundImage:[UIImage imageNamed:@"P150x20.png"] forBarMetrics:UIBarMetricsDefault];
56         // 状况二:同 navigationBar系统尺寸 保持一致的图片,效果展示不存在问题
57         [rootVC.navigationBar setBackgroundImage:[UIImage imageNamed:@"P414x44.png"] forBarMetrics:UIBarMetricsDefault];
58     }
59 
60     self.window.rootViewController = rootVC;
61     return YES;
62 }
63 
64 @end
复制代码

运行效果

■ UIToolBar

1. UIToolBar 存在于导航栏控制器底部,且默认被隐藏!下面是 UIToolBar 的使用方式

// - AppDelegate.m

复制代码
 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 2     // UIWidow
 3     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
 4     self.window.backgroundColor = [UIColor whiteColor];
 5     [self.window makeKeyAndVisible];
 6     // 根视图控制器
 7     ViewController * vc = [[ViewController alloc] init];
 8     UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
 9     nav.navigationBar.translucent = NO;
10     self.window.rootViewController = nav;
11     return YES;
12 }
复制代码

// - ViewController.m

复制代码
  1 #import "ViewController.h"
  2 #import "AppDelegate.h"
  3 @interface ViewController()
  4 @property(nonatomic,strong)UIImageView *imageView;
  5 @end
  6 
  7 @implementation ViewController
  8 - (void)viewDidLoad {
  9     [super viewDidLoad];
 10     self.view.backgroundColor = [UIColor yellowColor];
 11     // 导航栏是否透明
 12     // 半透明/隐藏:根视图从原点开始显示,大小同屏幕一致
 13     // 不透明:    根视图从导航栏底部开始显示,高度 = 主屏幕高度 - 导航栏高度
 14 
 15     // 在 APPDelegate.m 文件中,导航栏无论毛玻璃效果的设置与否
 16     // 在该里打印根视图的 frame,其尺寸始终同屏幕大小保持一致
 17     // 模拟器是 8 plus
 18     NSLog(@"%@",NSStringFromCGRect(self.view.frame));//  {{0, 0}, {414, 736}}
 19     // 但是在 viewWillAppear:方法中 尺寸就会发生改变
 20     // 原因是在执行 viewDidLoad 时,根视图还未显示
 21     // 就是说该时根视图还没有跟导航控制器发生联系
 22 
 23     // 也就意味着我们在 viewDidLoad:方法中 配置 toolbar 是没有任何效果的
 24     // [self toolbarDemo];
 25 
 26     //----------------------------------
 27     // 导航栏的 左/右 标题
 28     self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemReply target:self action:@selector(doClick:)];
 29     self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStylePlain target:self action:@selector(doClick:)];
 30 }
 31 
 32 // Toolbar
 33 - (void)viewWillAppear:(BOOL)animated{
 34     [super viewWillAppear:YES];
 35     NSLog(@"%@",NSStringFromCGRect(self.view.frame));
 36     // {{0, 64}, {414, 672}}
 37     [self toolbarDemo];
 38 
 39     NSLog(@"%@",NSStringFromCGRect(self.navigationController.toolbar.frame));
 40     // {{0, 687}, {414, 49}}
 41 }
 42 
 43 -(void)toolbarDemo{
 44 
 45     // 显示图片
 46     self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, self.view.frame.size.width - 20, self.view.frame.size.height - 64-10)];
 47     self.imageView.backgroundColor = [UIColor whiteColor];
 48     self.imageView.image = [UIImage imageNamed:@"0.jpg"];
 49     [self.view addSubview:self.imageView];
 50 
 51     //--------------------- Toolbar -------------------
 52 
 53     // 显示时带有动画效果
 54     // [self.navigationController setToolbarHidden:NO animated:YES];
 55     // 无动画效果
 56     self.navigationController.toolbarHidden = NO;
 57     self.navigationController.toolbar.translucent = YES;
 58     self.navigationController.toolbar.backgroundColor = [UIColor greenColor];
 59     // 背景图片:尺寸要求同 navigationBar,这里图片尺寸 414*49
 60     [self.navigationController.toolbar setBackgroundImage:[UIImage imageNamed:@"P414x49.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
 61     
 62     [[UIToolbar appearance]
 63         setBackgroundImage: [UIImage imageNamed:@"P414x49.png"]
 64         forToolbarPosition: UIToolbarPositionAny
 65         barMetrics: UIBarMetricsDefault];
 66    
 67     // 左:取消按钮
 68     UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(toolbarAction:)];
 69     item1.tintColor = [UIColor whiteColor];
 70 
 71     // 工具栏按钮要显示图片的话,需做以下处理
 72     UIImage *dealImage =[[self originImage:[UIImage imageNamed:@"toolItem.png"] scaleToSize:CGSizeMake(30, 30)] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
 73     UIBarButtonItem *item0 = [[UIBarButtonItem alloc] initWithImage:dealImage style:UIBarButtonItemStylePlain target:self action:@selector(toolbarAction:)];
 74 
 75     //右:显示 HOT
 76     UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"HOT" style:UIBarButtonItemStylePlain target:self action:@selector(toolbarAction:)];
 77     item2.tag = 103;
 78     item2.tintColor = [UIColor whiteColor];
 79 
 80     // UIBarButtonSystemItemFlexibleSpace:自动确定宽度并均分
 81     UIBarButtonItem *spaceButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
 82 
 83     // 添加 item
 84     self.toolbarItems = @[item1,spaceButtonItem,item0,spaceButtonItem,item2,];
 85 
 86 }
 87 
 88 // 随机显示图片
 89 - (void)toolbarAction:(UIBarButtonItem *)bItem{
 90 
 91     if (bItem.tag == 103) {
 92         self.imageView.image =[UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",arc4random()%4+1]];
 93     }else{
 94         self.imageView.image = [UIImage imageNamed:@""];
 95     }
 96 }
 97 
 98 // 图片尺寸:会造成图片失真的问题
 99 - (UIImage *)originImage:(UIImage*)image scaleToSize:(CGSize)size{
100     UIGraphicsBeginImageContext(size);
101     [image drawInRect:CGRectMake(0,0, size.width, size.height)];
102     UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
103     UIGraphicsEndImageContext();
104     return scaledImage;
105 }
106 
107 // 如何查找 UINavigationController
108 - (void)doClick:(UIBarButtonItem*)barBT{
109 
110     if ([barBT isEqual:self.navigationItem.leftBarButtonItem]) {
111         //方式一:利用 window
112         NSLog(@"window:%@",self.view.window.rootViewController);
113         //方式二:控制器的自带属性
114         NSLog(@"self.navigationController:%@",self.navigationController);
115     }else{
116         //方式三:使用 UIApplication(需引入头文件 AppDelegate.h)
117         NSLog(@"UIApplication:%@",((AppDelegate*)[UIApplication sharedApplication].delegate).window.rootViewController);
118         //方式四:响应者链
119         NSLog(@"响应者链:%@",[[[[[self.view nextResponder] nextResponder] nextResponder] nextResponder] nextResponder]);
120     }
121 }
122 
123 @end
复制代码

运行效果

TODO:代码 60行 toolBar 设置背景图片无效 

 

posted on   低头捡石頭  阅读(33)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示