大师学SwiftUI第6章 - 声明式用户界面 Part 3

安全域视图

SwiftUI还内置了创建安全文本框的视图。这一视图会把用户输入的字符替换成点以及隐藏敏感信息,比如密码。

  • SecureField(String, text: Binding):该初始化方法创建一个安全输入框。第一个参数定义占位文本,​​text​​参数为存储用户插入值的绑定属性。

实现方式与​​TextField​​视图相同,我们也可以应用相同的修饰符,如下所示。

示例6-29:使用安全文本框

struct ContentView: View {@State private var pass: String = ""var body: some View {VStack(spacing: 15) {Text(pass).padding()SecureField("Insert Password", text: $pass).textFieldStyle(.roundedBorder)Spacer()}.padding()}
}

​SecureField​​​视图和​​TextField​​视图外观一样。唯一的差别是其中的字符是隐藏的。

图6-15:安全文本框

图6-15:安全文本框

✍️跟我一起做:创建一个多平台项目。使用示例6-29中的代码更新​​ContentView​​视图。在输入框中插入字符。会看到字符被替换成为小黑点,如图6-15所示。

文本编辑器视图

SwiftUI还自带一个称为​​TextEditor​​的视图让用户可以插入多行文本。以下是该视图的初始化方法。

  • TextEditor(text: Binding):此初始化方法创建一个文本编辑器。​​text​​参数是存储用户所插入文本的绑定属性。

该视图可以接收前面用于格式化文本的​​TextField​​​和​​Text​​视图的一些修饰符。例如,我们可以设置视图中文本的对齐、行间距以及是否做错误检查。

示例6-30:实现一个文本编辑器

struct ContentView: View {@State private var text: String = ""var body: some View {TextEditor(text: $text).multilineTextAlignment(.leading).lineSpacing(10).autocorrectionDisabled(true).padding(8)}
}

图6-16:文本编辑器

图6-16:文本编辑器

开关视图

​Toggle​​视图创建一个在两种状态间切换的控件。默认在移动设备上显示为对用户友好的开关,在Mac上显示为复选框。该视图包含如下初始化方法。

  • Toggle(String, isOn: Binding):该初始化方法创建一个​​Toggle​​​视图。第一个参数定义标签,​​isOn​​参数为存储当前状态的绑定属性。本视图还自带有一个由闭包返回视图的标签(Toggle(isOn: Binding, label: Closure))。

该视图要求绑定属性存储当前值。在下例中,我们提供了一个​​@State​​属性并使用属性值来选取适当的标签。

示例6-31:实现一个开关

struct ContentView: View {@State private var currentState: Bool = truevar body: some View {VStack {Toggle(isOn: $currentState, label: {Text(currentState ? "On" : "Off")})Spacer()}.padding()}
}

示例6-31中的代码使用三元运算符来检测​​currentState​​​属性的值并显示相应的文本(On或Off)。默认我们设置属性值为​​true​​,因此开关处于打开状态并在屏幕上显示On标签,但如果点击开关,就会关闭,视图更新为显示Off标签。

图6-17:打开和关闭开关

图6-17:打开和关闭开关

✍️跟我一起做:创建一个多平台项目。使用示例6-31中的代码更新​​ContentView​​视图。点击打开或关闭开关。使用这个项目测试下面的例子。

赋值给​​label​​参数的闭包可以包含另外一个定义副标题的视图,如下例所示。

示例6-32:添加副标题

struct ContentView: View {@State private var currentState: Bool = truevar body: some View {VStack {Toggle(isOn: $currentState, label: {Text(currentState ? "On" : "Off")Text("Enable or Disable")})Spacer()}.padding()}
}

图6-18:带标题和副标题的开关

图6-18:带标题和副标题的开关

​Toggle​​​视图创建了一个包含标题和控件中间为弹性空间的横向布局,结果就是整个视图占满容器的横向空间,标签和控件位于两端。如果希望对视图的位置和尺寸做精确控制,可以应用此前介绍过的​​fixedSize​​修饰符来降低视图的尺寸,或使用如下修饰符隐藏标签。

  • labelsHidden():此修饰符隐藏赋值给控件的标签。

这一修饰符适用于多款控件,但对开关尤为有用。下例展示了如何实现它来为控件定义一个自定义标签。

示例6-33:为​​Toggle​​视图定义一个自定义标签

struct ContentView: View {@State private var currentState: Bool = truevar body: some View {HStack {Toggle("", isOn: $currentState).labelsHidden()Text(currentState ? "On" : "Off").padding().background(Color(currentState ? .yellow : .gray))}.padding()}
}

视图现在为控件的大小并在屏幕中心显示。标签不再显示 ,因此我们将其声明为空字符串,但在当前值的侧边包含一个​​Text​​视图。

图6-19:自定义大小以及开关的标签

图6-19:自定义大小以及开关的标签

类似​​Button​​​视图,​​Toggle​​视图也实现了修饰符用于定义控件的样式。

  • toggleStyle(ToggleStyle):这一修饰符定义开关的样式。参数是一个遵循​​ToggleStyle​​​协议的结构体。为创建标准的结构体,框架包含了​​automatic​​​、​​button​​​、​​checkbox​​​和​​switch​​这些属性。

默认值为​​automatic​​​,表示控件的样式由系统选择。如果希望保持同一种样式,可以赋值​​switch​​​或​​checkbox​​​(仅能用于Mac)。这些值用于指定标准样式,但框架还内置了​​button​​值来创建完全不同类型的控件。在将这一样式赋值给视图时,系统显示一个开关按钮来表示开和关的状态。在按钮处于开的状态时,高亮显示,否则显示 为标准按钮。

示例6-34:实现一个开关按钮

struct ContentView: View {@State private var currentState: Bool = truevar body: some View {HStack {Toggle(isOn: $currentState, label: {Label("Send", systemImage: "mail")}).toggleStyle(.button)}.padding()}
}

图6-20:切换按钮为开关状态

图6-20:切换按钮为开关状态

框架提供的样式是有限的,但我们可以自行创建。只需要定义一个遵循​​ToggleStyle​​协议的结构体。该协议要求结构体实现如下方法。

  • makeBody(configuration: Configuration):该方法定义并返回一个替换开关主体的视图。​​configuration​​​参数是一个​​Configuration​​类型的值,包含控件相关信息。

这个方法接收一个类型为​​Configuration​​​的值,是​​ToggleStyleConfiguration​​的类型别名,包含如下属性来返回控件相关的信息。

  • isOn:该属性返回一个表示开关处于开或关状态的布尔值。
  • label:该属性返回定义开关标签的视图。

​isOn​​​是一个绑定属性,创建与视图的双向绑定,因此我们可以读取并修改其值来激活或停用控件。在下例中,我们创建了一个类似复选框的​​Toggle​​视图。点击控件时,图形变换颜色来表示当前的状态(灰色为停用,绿色为激活)。

示例6-35:定义一个自定义​​Toggle​​视图

struct MyStyle: ToggleStyle {func makeBody(configuration: Configuration) -> some View {HStack(alignment: .center) {configuration.labelSpacer()Image(systemName: "checkmark.rectangle.fill").font(.largeTitle).foregroundColor(configuration.isOn ? Color.green : Color.gray).onTapGesture {configuration.$isOn.wrappedValue.toggle()}}}
}struct ContentView: View {@State private var currentState: Bool = falsevar body: some View {VStack {HStack {Toggle("Enabled", isOn: $currentState).toggleStyle(MyStyle())Spacer()}.padding()}}
}

在自定义​​Toggle​​​视图前必须要考虑几件事。首先,​​Configuration​​​结构体的​​label​​​属性包含一个控件当前标签的视图副本,因此如果想要保留这个标签,必须在新的内容中包含这个值。第二,​​Toggle​​​视图使用​​HStack​​​视图和标签与控件间的​​Spacer​​​视图来设计。如果想要保留标准设计,必须保持这种布局。第三,我们负责响应用户的交互以及更新控件的状态,因此必须检测手势并在用户执行手势时通过修改​​isOn​​属性的值来变更控件状态。

示例6-35中,我们定义了一个结构体​​MyStyle​​​并实现了所要求的​​makeBody()​​​方法来为​​Toggle​​​视图提供新设计。为保留标准样式,我们使用​​HStack​​​视图来包装视图并使用​​Spacer​​​视图来分隔标签与控件。首先我们读取​​label​​​属性的值来添加当前标签,然后声明​​Spacer​​​视图,最后声明一个​​Image​​​视图来展示外观像复选框的SF图标。为将​​Image​​​视图转换为控件,我们使用​​font()​​​修饰符定义其大小,应用​​foregroundColor()​​​修饰符来根据​​isOn​​​属性的当前值来修改图标的颜色,最后,使用​​onTapGesture()​​​修饰符监测用户何时点击​​Image​​​视图。我们会在​​第12章​​​中学习更多有关手势修饰符的知识。现在,只需要知道这一修饰符在每次用户点击视图时执行一个闭包。在这个闭包中,我们访问​​isOn​​​属性的绑定值并通过对​​wrappedValue​​​属性中的布尔值应用​​toggle()​​​修饰符切换值。(本例中,绑定值的setter是私有的,因此通过​​wrappedValue​​属性访问它,本章前面做过讲解。)这会修改该属性的当前值,进而改变控件的状态,将其打开及关闭。

图6-21:Toggle视图的自定义样式

图6-21:​​Toggle​​视图的自定义样式

滑块视图

​Slider​​视图创建一个控件,允许用户选择一个范围内的值。显示为一个带结点的横条,结点对应所选择的值。该结构体包含如下初始化方法。

  • Slider(value: Binding, in: Range, step: Float, onEditingChanged: Closure):这个初始化方法创建一个​​Slider​​视图。​​value​​参数是希望用于存储当前值的绑定属性,​​in​​参数是指定用户选择的最大、最小值范围,​​step​​参数表示当前值递增或递减的量,​​onEditingChanged​​参数是在用户开始或结束移动滑块时执行的闭包。

要创建滑动,必须至少提供一个​​@State​​属性来存储值以及一个决定允许最小和最值的范围。

示例6-36:创建滑块

struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {Text("Current Value: \(currentValue.formatted(.number.precision(.fractionLength(0))))")Slider(value: $currentValue, in: 0...10, step: 1.0)Spacer()}.padding()}
}

示例6-36中的代码创建一个0到10的滑块,以​​Text​​视图显示当前值。​​Slider​​视图接收类型为​​Float​​和​​Double​​类型的值,因此允许我们选择浮点值,但我们可以通过声明​​step​​参数值为1.0来指定希望用户选择的是整数,如本例所示。(注意我们需要使用第4章中介绍的​​formatted()​​方法将​​Text​​视图的值格式化为整数。)因为​​currentValue​​属性使用数字5进行了初始化,结点的初始位置就位于正中间。

图6-22:整数值滑块

图6-22:整数值滑块

​Slider​​初始化方法还内置了​​onEdittingChanged​​参数,接收一个闭包,闭包接收表示用户开始或结束移动滑块的布尔值。我们可以使用它来高亮显示编辑中的值,如下例所示。

示例6-37:响应滑块状态

struct ContentView: View {@State private var currentValue: Float = 5@State private var textAcitve: Bool = falsevar body: some View {VStack {Text("Current Value: \(currentValue.formatted(.number.precision(.fractionLength(0))))").padding().background(textAcitve ? Color.yellow : Color.clear)Slider(value: $currentValue, in: 0...10, step: 1.0, onEditingChanged: { self.textAcitve = $0 })Spacer()}.padding()}
}

示例6-37中的视图包含一个名为​​textActive​​的新​​@State​​属性。赋值给闭包的​​onEdittingChanged​​参数在用户开始移动滑块时对该属性赋值​​true​​,释放结点时赋值​​false​​。​​Text​​视图的​​background()​​修饰符读取该值根据当前状态设置不同的背景色。因此,在用户移动滑块时显示当前值的文本为黄色背景,否则没有背景色。

进度视图

SwiftUi内置有​​ProgressView​​视图来用于创建进度条。该视图设计用于显示任务的进度。

  • ProgressView(String, value: Binding, total: Double):此初始化方法创建一个进度条。第一个参数指定标签,​​value​​参数表示当前进度,​​total​​参数指定表示任务完成度的值。(默认值为0.0到1.0)。

视图的实现非常直观。我们只需要一个表示当前进度的属性值。

示例6-38:显示进度

struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {ProgressView(value: currentValue, total: 10)Spacer()}.padding()}
}

这一​​ProgressView​​视图值由0.0到10.0,初始值为5(通过​​currentValue​​赋了初始值),因此进度位于中心。

图6-24:进度条

图6-24:进度条

​ProgressView​​视图设计用于显示任务即时的进度,比如从服务端下载的当前数据量,或是还差多少完成任务。稍后我们会学习如何执行其中一些任务,但现在我们通过​​Slider​​视图来做测试,如下所示。

示例6-39:模拟进度

struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {ProgressView(value: currentValue, total: 10)Slider(value: $currentValue, in: 0...10)Spacer()}.padding()}
}

本例中,我们对​​Slider​​和​​ProgressView​​设置了相同的值。范围为0到10,因此每当我们移动滑块时,进度条就显示相同值。

图6-25:使用中的进度条

图6-25:使用中的进度条

​ProgressView​​结构体内置了如下修饰符用于定义进度条的样式。

  • progressViewStyle(ProgressViewStyle):这一修饰符指定​​ProgressView​​视图的颜色 。参数是一个遵循​​ProgressViewStyle​​协议的结构体。框架定义了​​automatic​​、​​circular​​和​​linear​​属性来创建标准视图。

默认样式为​​automatic​​,表示视图显示为一个线性进度条,但我们可以指定​​circular​​值来创建活动指示。这是一个表示任务在处理中的转盘,但不同于进度条,这类指示符没有隐性界限,所示无需指定任何值,如下所示。

示例6-40:显示活动指示器

struct ContentView: View {@State private var currentValue: Float = 5var body: some View {VStack {ProgressView().progressViewStyle(.circular)Spacer()}.padding()}
}

图6-26:活动指示器

图6-26:活动指示器

其它相关内容请见​​虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记​​

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

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

相关文章

leetcode 013二维区域和检索---矩阵不可变

给定一个二维矩阵 matrix,以下类型的多个请求: 计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。 实现 NumMatrix 类: NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进…

Quartus II使用小技巧

工程结构: 在建立完某项设计的文件后,依次在其里面新建四个文件夹,分别为:rtl、qprj、msim、doc。 rtl文件夹用于存放设计的源文件。 doc文件夹用于存放设计的一些文档性的资料。 qprj文件夹用于存放quaruts 工程以及quartus生…

Git入门详细教程

一、Git概述🎇 Git官网 Git是一个开源的分布式版本控制系统,用于跟踪文件的变化和协作开发。它允许多个开发者在同一项目中共同工作,并能够有效地管理代码的版本和历史记录。Git可以帮助开发团队更好地协作,追踪代码变更&#xf…

记一次多平台免杀PHP木马的制作过程

注意:本文转载自本作者稀土掘金博客 博客地址: 御坂19008号 的个人主页 - 动态 - 掘金 文章目录 前言声明绕过情况使用方法运行环境绕过点介绍技术原理讲解变量传值覆盖模块代码执行阻断模块InazumaPuzzle程序锁定器PerlinNoise危险函数生成与执行类构造…

Android 基础技术——addView 流程

笔者希望做一个系列,整理 Android 基础技术,本章是关于 addView 在了解 addView 流程之前,先回答下以下几个问题: PhoneWindow是什么时候创建的? DectorView 是什么? DectorView 是什么时候创建的&#xf…

Oracle行转列函数,列转行函数

Oracle行转列函数,列转行函数 Oracle 可以通过PIVOT,UNPIVOT,分解一行里面的值为多个列,及来合并多个列为一行。 PIVOT PIVOT是用于将行数据转换为列数据的查询操作(类似数据透视表)。通过使用PIVOT,您可以按照特定的列值将数据进行汇总,并将…

Flowable 生成流程图

/*** 生成流程图** param processId 任务ID*/ RequestMapping("/diagram/{processId}") public void genProcessDiagram(HttpServletResponse response,PathVariable("processId") String processId) {InputStream inputStream flowTaskService.diagram(p…

SpringCloud整合Zookeeper代替Eureka案例

文章目录 本期代码下载地址zookeeper简介zookeeper下载安装新建服务提供者测试 新建消费者测试 本期代码下载地址 地址:https://github.com/13thm/study_springcloud/tree/main/days4 zookeeper简介 zookeeper是一个分布式协调工具,可以实现注册中心功能 关闭Lin…

WampServer

开发笔记 推荐链接php无法保存SESSION问题部署SSL时候产生的问题 推荐链接 链接目录 php无法保存SESSION问题 php.ini文件和phpForApache.ini 文件 里面都有 对路径的控制,相关路径问题可能也需要进行修改,打开文件搜索wamp64或wamp 就可以看到了&…

线程池--JAVA

虽然线程是轻量级进程,但是如果当创建和销毁的的频率非常之高,那么它也就会消耗很多的资源。 而线程池就是用来优化线程频繁创建和销毁的场景,减少线程创建、销毁的频率。 ExecutorService JAVA标准库为我们实现了线程池,Execu…

windows11上安装虚拟机VMware

1、安装虚拟机(待补充) 第二步:安装VMware tools 实现windows文件上传到虚拟机中 1、安装好虚拟机后,查看虚拟机ip用Xshell连接虚拟机,并安装VMware tools(只有安装了VMware tools才能实现虚拟机和本机的文件共享。在…

无人机航迹规划(四):七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划(提供MATLAB代码)

一、七种算法(DBO、LO、SWO、COA、LSO、KOA、GRO)简介 1、蜣螂优化算法DBO 蜣螂优化算法(Dung beetle optimizer,DBO)由Jiankai Xue和Bo Shen于2022年提出,该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖…

Python编辑开发---pycharm pro 2023 中文

PyCharm Pro 2023是一款功能强大的Python集成开发环境(IDE),旨在提高Python开发人员的生产力。它提供了智能代码编辑、实时代码分析和调试工具,支持版本控制和数据库工具,以及可扩展的插件系统。PyCharm Pro 2023可在多…

什么是区块链?

区块链 区块链 (英语:blockchain)是借由 密码学 与 共识机制 等技术建立,存储数据的 保证不可篡改和不可伪造的 分布式技术。 什么是区块 区块 就是将一批数据打包在一起,并且给打包出来的区块编号。第一个区块的编…

Kylin 安装novnc 远程访问

noVNC可以使用浏览器直接访问服务器,而不需要使用VNC客户端。 1.初始环境 关闭防火墙或允许IP访问本机 2.安装依赖 dnf install -y tigervnc-server git 3.git下载novnc git clone https://github.com/novnc/noVNC.git git clone https://gitee.com/yangyizhao…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C) Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过NEOAPI SDK使用相机日志跟踪功能1.引用合适的类文件2.通过NEOAPI SDK使用相机日志跟踪功能3.通…

如何用数据赋能社媒营销决策?

在数字化时代,越来越多的商家开始意识到数据分析对于改善经营的重要性。 传统决策更多依赖过往经验、商业直觉、他人的思路模板等方法,或者依靠描述性统计、简单的数据分析。在数字时代,则通过精细化数据分析,做出更明智的营销决策…

S2-08 ESP-IDF开发 : 存储

S2-06 和 S2-07 暂时先不发,课上没给同学们将,分别是 DMA 和 USB 章节,作为专项讲 存储 ESP32 系列芯片中,不同型号的芯片所携带的 ROM、SRAM、RCT SRAM、PSRAM 以及 Flash大小不同,他们的作用如下: SRAM…

2023年总结我所经历的技术大变革

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不仅…

如何使用支付宝沙箱环境本地配置模拟支付并结合内网穿透远程调试

文章目录 前言1. 下载当面付demo2. 修改配置文件3. 打包成web服务4. 局域网测试5. 内网穿透6. 测试公网访问7. 配置二级子域名8. 测试使用固定二级子域名访问 正文开始前给大家推荐个网站,前些天发现了一个巨牛的 人工智能学习网站, 通俗易懂&#xff…