UI学习--导航控制器

导航控制器

  • 导航控制器基础
    • 基本概念
    • 具体使用
  • 导航控制器切换
    • 演示
    • 具体使用
    • 注意
  • 导航栏与工具栏
    • 基本概念
    • 具体使用:
  • 总结


导航控制器基础

基本概念

  • 根视图控制器(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是将视图控制器推出栈顶。
而因为导航控制器对象本身是没有改变的,所以我们设置了根视图的导航控制器,就设置了所有视图的导航控制器


导航栏与工具栏

基本概念

导航栏前面已经介绍了,我们在此着重介绍工具栏。
工具栏的组件:

  1. 固定空间按钮(Fixed Space Bar Button):固定空间按钮是另一种特殊类型的工具栏按钮,用于创建固定宽度的间距。它可以用于调整按钮之间的间距或在工具栏上创建对齐效果。
  2. 标签(Label):用于显示相关的信息或标题,提供上下文或描述工具栏中的操作。
  3. 图片视图(Image View):用于显示图标、图像或其他视觉元素。图像视图可以代表特定的操作或提供视觉上的识别。
  4. 自定义视图(Custom View):自定义的视图元素,自定义视图可以是任何 UIView 的子类,允许你在工具栏上添加自定义的界面元素,如文本输入框、开关按钮等。

工具栏的基本元素:

  1. 工具栏按钮(Toolbar Button):工具栏中的单个按钮,可以通过点击来执行特定操作或导航到其他屏幕。
  2. 工具栏项(ToolbarItem):工具栏中的一个单独元素,可以包含一个或多个工具栏按钮。
  3. 工具栏控制器(ToolbarController):用于管理工具栏的视图控制器,可以使用工具栏控制器来添加、删除和重新排列工具栏项。
  4. 工具栏样式(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学习的重要一部分,经过这篇总结融会贯通,我觉得我又行咯。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/24349.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

压缩大文件消耗电脑CPU资源达到33%以上

今天用7-Zip压缩一个大文件,文件大小是9G多,这时能听到电脑风扇声音,查看了一下电脑资源使用情况,确实增加了不少。 下面是两张图片,图片上有电脑资源使用数据。

Spring系统学习 -Spring IOC 的XML管理Bean之bean的获取、依赖注入值的方式

在Spring框架中,XML配置是最传统和最常见的方式之一,用于管理Bean的创建、依赖注入和生命周期等。这个在Spring中我们使用算是常用的,我们需要根据Spring的基于XML管理Bean了解相关Spring中常用的获取bean的方式、依赖注入值的几种方式等等。…

Maven项目打包成jar项目后运行报错误: 找不到或无法加载主类 Main.Main 和 jar中没有主清单属性解决方案

已经用maven工程的package功能进行了打包 找不到或无法加载主类 Main.Main 规定主类 主要在maven的配置文件当中 这边一定要绑定自己的启动类 jar中没有主清单属性 删掉这一行就行哈 正确的插件代码 <plugin><groupId>org.springframework.boot</groupId&…

毫米波SDK使用1

本文档是AM273x等毫米波雷达处理器SDK的配置和使用&#xff0c;主要参考TI的官方文档《mmwave mcuplus sdk user guide》。这里仅摘取其中重要的部分&#xff0c;其余枝节可参考原文。 2 系统概览 mmWave SDK分为两个主要组件:mmWave套件和mmWave演示。 2.1. mmWave套件 mmWa…

AXI Quad SPI IP核基于AXI-Lite接口的标准SPI设计指南

在标准SPI配置下&#xff0c;SPI设备除了包含基本的SPI特性外&#xff0c;还具备以下一些标准功能&#xff0c;这些功能如下所示&#xff1a; 支持FPGA内部的多主设备配置&#xff0c;其中使用单独的_I&#xff08;输入&#xff09;、_O&#xff08;输出&#xff09;、_T&…

FM148A,FM146B运行备件

FM148A,FM146B运行备件。电源保险丝仓主控底座的保险丝仓示意图底座上共有两个保险丝&#xff08;800mA&#xff09;&#xff0c;FM148A,FM146B运行备件。&#xff08;10&#xff5e;73&#xff09;30/195主控单元2.K-CUT014槽底座地址接口主控站地址拨开关从上到下为二进制数的…

开发网站,如何给上传图片的服务器目录授权

开发网站&#xff0c;上传图像时提示”上传图片失败&#xff0c;Impossible to create the root directory /var/www/html/xxxxx/public/uploads/avatar/20240608.“ 在Ubuntu上&#xff0c;你可以通过调整文件夹权限来解决这个问题。首先&#xff0c;确保Web服务器&#xff08…

【笔记】从零开始做一个精灵龙女-装备阶段

这里只记录相对重要的步骤和一些思路 但是头发那块很详细哦~ &#xff08;标的小数字不用在意&#xff0c;那个是我网课的时长记录&#xff09; 耳环 1.创建一个圆环&#xff0c;调整参数 做好后再复制一个小的 肩甲 2.0-2.4 1.创建圆柱体/球体也可 然后把底部的两个点删…

Xsens动作捕捉系统:角色动画制作与运动分析领域的先进工具

随着传感器技术的不断进步&#xff0c;动作捕捉技术现在更加趋向于民用化&#xff0c;拥有价格优势的惯性动作捕捉系统现在更多的出现在独立动画工作室与国内外多所高校的实际项目应用中。 凭借无场地限制、价格优惠、校准使用方便、数据采集精确等多项优势&#xff0c;Xsens惯…

[AI Google] 双子座模型家族迎来新突破:更快的模型、更长的上下文、AI代理等更多功能

Google发布了Gemini模型家族的更新&#xff0c;包括新的1.5 Flash模型&#xff0c;该模型旨在提高速度和效率&#xff0c;以及Project Astra&#xff0c;这是对未来AI助手愿景的展示。1.5 Flash是专为大规模高频任务优化的轻量级模型&#xff0c;具有突破性的长上下文窗口。同时…

Diffusers代码学习: IP-Adapter Inpainting

IP-Adapter还可以通过Inpainting自动管道和蒙图方式生成目标图片。 # 以下代码为程序运行进行设置&#xff0c;使用Inpainting 的自动管道&#xff0c; import os os.environ["HF_ENDPOINT"] "https://hf-mirror.com"from diffusers import AutoPipelin…

【java】速度搭建一个springboot项目

使用软件&#xff1a;IDEA&#xff0c;mysql 使用框架&#xff1a;springboot mybatis-plus druid 坑点 使用IDEA搭建一个springboot项目的时候&#xff0c;需要考虑一下IDEA版本支持的JDK版本以及maven版本。否则再构建项目&#xff0c;引入pom的时候就会报错。 需要检查…

04 uboot 编译与调试

新手不需要详细掌握 uboot,只需要知道它是一个什么东西即可,工作中也只是改一些参数而已。 1、uboot 是什么 Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段 bootloader 程序。这段 bootloader 程序会先初始化 DDR 等外设,然后将 Linux 内…

利用PowerQuery控制数据行数

PowerBI报表在开发的过程中&#xff0c;经常会遇到数据量非常庞大的情况&#xff0c;在这种情况下&#xff0c;本机连接数据源如果不进行特殊处理的话&#xff0c;那么刷新数据的时候可能会发生数据刷新时间过长、数据加载内存错误、开发过程中构建DAX卡顿等情况。 那么在实际开…

不确定性+电动汽车!含高比例新能源和多类型电动汽车的配电网能量管理程序代码!

前言 能源供应的可持续性和清洁性是当今世界共同关注的议题&#xff0c;配电网与可再生能源发电相结合&#xff0c;通过多能互补和梯级利用&#xff0c;在不同时空取长补短&#xff0c;提高能源利用率&#xff0c;减少温室气体排放&#xff0c;是解决能源短缺和环境问题的有效…

[职场] 关于薪酬需要知道的两个知识点 #知识分享#知识分享

关于薪酬需要知道的两个知识点 薪酬问题是面试过程中比较核心的问题&#xff0c;也是每次面试必问的。如果你进入到面试的后一阶段&#xff0c;这类问题可以让面试官或企业判断求职者的要求是否符合企业的薪酬标准&#xff0c;并进一步判断求职者对自身价值的认可程度。关于薪…

数据结构之快速排序算法(快排)【图文详解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

【Java数据结构】详解Stack与Queue(三)

&#x1f512;文章目录&#xff1a; 1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 2. 队列&#xff08;Queue&#xff09; 2.1队列的概念 2.2队列的方法 2.3队列的使用 2.4循环队列 循环队列的介绍 循环队列图 如何区分循环队列是满还是空…

外挂知识库的基本知识与内容

外挂知识库 1.什么是rag&#xff1f; RAG,即LLM在回答问题或生成文本时&#xff0c;会先从大量文档中检索出相关的信息&#xff0c;然后基于这些信息生成回答或文本&#xff0c;从而提高预测质量。 2.外挂知识库的实现思路 只用几十万量级的数据对大模型进行微调并不能很好…

第五十六周:文献阅读

目录 摘要 Abstract 文献阅读&#xff1a;应用于地表水总磷浓度预测的可解释CEEMDAN-FE-LSTM-Transformer混合模型 一、现有问题 二、提出方法 三、方法论 1、CEEMDAN&#xff08;带自适应噪声的完全包络经验模式分解&#xff09; 2、FE&#xff08;模糊熵 &#xff09…