Swift UI 学习(3)
1.sheet
sheet,又称为工作簿,会创建一个从底部弹出的视图(但不会占满屏幕),下面看一个使用样例:
在sheet中我们绑定了一个变量,这是让视图的显示随着变量的改变而改变。
当我们点击按钮时,会通过sheet弹出一个新视图:
可以看到,视图没有占满所有的视图空间。此外,该视图类似于一个ScrollView,我们可以通过滑动来关闭它。
环境变量
如果你想设计一个一键关闭的按钮,我们这里使用一个在sheet中常用的关闭,常用于关闭和返回视图。
presentationMode
是 SwiftUI 中的一个环境变量,它提供对当前表示模式的访问,表示模式控制着视图的呈现方式。它通常用于控制模态视图(例如 sheet 和 popover)的显示和关闭。
中间的反斜杠代表的类似一个绑定,后面是可以自定义的变量名。(这里只是和前面的保持一致)
我们声明该环境变量后,我们可以在Button的语句中写入如下语句:
可以看到,这里我们就设计了一个白色的X标志,当我们点击时即可一键关闭视图。
这里拓展一点,你可以看到在这里时我的sheet是占满了整个屏幕的,这是因为我更换了视图预览的缘故。当我们在创建第二个视图时,我们需要通过实时更新的UI来修改我们的视图,这时候我们就可以把UI更新的视图切换到我们要修改的视图:
将最后的部分修改为新视图的名称即可。
上面是一种常用的方法,此外改环境变量还有以下使用:
- **检测模态视图何时被关闭:**你可以使用
presentationMode.wrappedValue.isPresented
来检测模态视图何时被关闭。 - **自定义模态视图的过渡:**你可以使用
presentationMode.wrappedValue.presentationTransition
来自定义模态视图的过渡动画。
FullScreenCover
FullScreenCover是一种类似于sheet的显示视图,它于sheet有几点不同:
- **FullScreenCover:**覆盖整个屏幕,将底层视图完全隐藏。
- **FullScreenCover:**无法通过拖动来关闭,只能进行设计按钮或点击背景。
下面是FullScreenCover的图例:
注意:不管是FullScreenCover还是sheet,都不建议在使用它们时添加逻辑判断如if else 语句,这可能会导致未知的错误
2.NavigatioView
在许多网页中,我们总能看到一个位于顶端的导航栏,它可以给我们提供很多的便利和方向。在SwiftUI中,NavigationView就是用来做导航栏的元素。先来看下它的基本使用:
首先我们创建一个NavigationView并创建一个滚动视图,将文本放入滚动视图中。
可以看到,我们的文本并没有从顶部开始,这是因为NavigationView自动占用了顶部的一部分空间,但我们没有将其进行设置,因此我们现在看不到导航栏。
现在让我们为导航栏加上标题。
现在我们就可以看到导航栏的位置了,对于标题,SwiftUI中还提供了三种不同的放置方式,我们可以通过使用navigationBarTitleDisplayMode()来修改,
navigationBarTitleDisplayMode
-
(1) inline
-
标题位于导航栏的中央,与其他导航栏项目(如按钮)齐平。
-
-
(2) large
-
标题位于导航栏的顶部,占据导航栏的大部分高度。
-
标题的字体大小更大,更醒目。
-
这是默认的放置方式。
-
(3)automatic
-
SwiftUI 会根据导航栏的宽度和内容自动选择
inline
或large
显示模式。 -
如果导航栏较窄,标题将显示为
inline
模式。如果导航栏较宽,标题将显示为large
模式。当你向上滑动时又large变为**inline
**
此外,如果你不想显示导航栏,我们也可以采用navigationBarHidden来进行隐藏导航栏,且不占用原来位置。
NavigationLink
接下来我们介绍导航栏另一个重要元素,NavigationLink(),就是导航链接,可以切换到另一个新的视图。
这时我们的视图出现了一个蓝色的文本标题,单击文本标题就会切换到下一个视图,且该视图中含有一个Text(默认切换方式向右滑动),destination的意思就是切换的目的地
可以看到,这时我们在主视图的导航栏就成了一个返回的图标,点击即可返回之前的视图。
我们可以通过destination来设置我们到达的视图是哪一个,我们可以将我们自己设置的第二视图放入其中,这样我们就有了一个完美的跳转导航。
我们还可以进行嵌套式导航,下面看一个示例:
首先定义一个第二视图,并在第二视图中添加上NavigationLink:
接着,我们在主视图中的NavigationView里面添加一个NavigationLink,并将其的destination设置为第二视图的名称。
这时我们可以在主视图点击蓝色的按钮,视图就会跳转到第二视图:
点击第二视图的蓝色按钮,我们就会跳转到第三视图。
这样我们可以很轻易的实现视图与视图之间的跳转和联系。每一个视图的跳转后仍会保留原视图的导航栏元素返回元素,方便我们进行返回。
如果我们不想使用这个元素作为返回的按钮。前面提到,我们可以使navigationBarHidden来进行导航栏的隐藏,这里同样也可以做到。同时,这里可以使用sheet中提到的环境变量来达到相同的目的。
navigationBarItems
网页的导航栏中有各种各样的元素来方便我们的跳转,在SwiftUI中,我们可以使用navigationBarItems
来进行导航栏元素的添加。下面看一个示例:
这样我们就在导航栏的左右各放置了一个图标。
这些图标可以设计的功能多样,同样可以做到进行视图的转换:
我们通过添加NavigationLink图标也具有了跳转视图的功能。
NavigationLink会使得元素改变为默认的蓝色,如果我们想修改颜色,可以使用accentColor来做到。
3.List
List(列表)也是一个常用的元素,我们在日常添加和删除元素时列表会是一个重要的帮手。下面看列表的定义使用:
可以看到,列表和Vstack十分类似,也是呈现垂直摆放的形态。列表可以通过Foreach循环来进行每个行内容的确定,下面看一个示例:
我们使用Foreach循环对fruits中个每个元素进行了遍历,并使用section元素对其进行了一个分组。下面简单介绍一下section:
-
Section 组件用于在 SwiftUI 中对列表或表格中的项目进行分组。
-
Section(header: 文本、视图或任何其他可渲染的内容 ) {footer: // 项目列表或表格行 }
接下来我们介绍一个List中十分好用的功能,元素的删除,移动,添加。
onDelete
我们写入onDelete函数名:
可以看到它的基本用法,写入后我们对列表进行向左滑动:
可以发现我们现在的列表多了一个向左滑动删除的功能,接下来补全onDelete中的函数变量:
这时我们就可以做到滑动并删除元素的功能。短短两行就实现了元素的删除功能,这就是List的强大之处,甚至我们还可以进行进一步的简化:
将执行语句写入一个函数中
这时我们就可以只保留一个delete的函数名
onMove
上文中我们介绍了使用NavigationView来给文章添加导航栏,这里我们使用NavigationView中的navigationBarltems来进行界面的优化,使用内置组件E.EditButton
,EditButton
组件允许用户在视图中启用或禁用编辑模式。可以用于重新排列项目和删除或添加项目。
我们添加.EditButton
组件放在导航栏中,并点击
可以看到出现了编辑模式,我们等会进行移动时就是在编辑模式下进行,而现在我们只能执行之前写入的删除代码。
下面我们写入移动代码onMove
实际时调用move函数将一个索引移动到另一个索引,indices是旧位置,newOffset是新位置。
现在我们打开编辑模式,可以看到旁边有一个小标志,现在点击那个标志就可以进行元素的移动
现在,我们就将peach移动到第一位。
当然,你也可以把语句写在一个函数中:
这样代码就可以简化为和onDelete简化一样的格式。
onInsert
SwiftUI中我们一般使用onInsert来进行列表的添加操作,当然它的操作和数组的添加十分类似,我们可以借助函数来进行不同类型的添加。
我们这里设计了一个insetItem函数来进行自定义添加,此外需要注意的是列表的元素插入需要写allowsInsertion(true),来让列表实现元素的插入。下面是insetItem函数的一般写法,其它写法可自行尝试。
func insertItem(at index: Int) {
items.insert("要插入的元素", at: index)
}
listStyle
List在swiftUI我们可以自定义它的样式,如果你不喜欢它的原版样式,我们可以对样式进行选择
不同的listStyle有不同的显示效果,如果想找到最合适自己的建议进行一个个尝试。
注意:listStyle在不同的设备上可能有不一样的显示效果,建议在对应的设备上进行预览尝试
4.alert
在使用应用程序时,我们总能遇到各种各样的弹窗,在swiftUI中我们就是使用alert来进行弹窗的弹出设置。下面看一行代码:
我们在按钮中设置了一个警报,点击按钮就会弹出警告窗。
你会发现我们写了.alert和Alert两个很像的数据类型,下面我们简单说下它们的分别的应用场景:
Alert
是一个数据结构,用于表示警报。当您需要创建和配置一个警报时,请使用Alert
结构体.alert
是视图修饰符,它用于在视图中显示警报。
警报框的定义多种多样,我们可以在Alert中自定义警告框的内容。下面看一段代码:
这段代码中我们定义了警告框弹出的标题和信息,并定义了两个按钮,在Alert中的button中有几种类型,下面简单介绍一下:
.default()
:一个标准的蓝色按钮,通常用于确认或执行主要操作。.cancel()
:一个蓝色的按钮,通常用于取消或关闭警报。.destructive()
:一个红色的按钮,通常用于执行破坏性操作,例如删除数据。
注意:一个警告框中最多有两个按钮
我们可以定义动态的警告框内容,先定义变量,然后在每个按钮中进行传入数据改变变量的值,最后再进行警告框的弹出
dismissButton是单个默认的取消警告框按钮
如果不想进行多个变量的设置,我们可以使用枚举类型,在一个枚举类型中写入所有需要的元素,并将警告框的设计写在一个函数中,使得代码的区域更集中。
定义一个枚举类型。
定义一个变量来储存枚举类型。(这里?号表示可选,不存入则为空)
接下来将设计对应按钮中的枚举元素。
最后我们只需要在函数中写入对应的代码即可。
5.ConfirmationDialog
ConfirmationDialog和alert十分相似,,不同的是一个出现在屏幕的中间,一个出现在屏幕的下方。而且ConfirmationDialog可以在弹出界面中设计多个按钮,而alert最多只能设计两个,在需要用户进行三个以上判断时常用ConfirmationDialog
下面来看基本用法:
它的语法基本与alert完全相同(拥有的按钮类型也完全相同),不同的是他可以在自己的内部设计多个按钮,达到更多的目的选择。
可以看到,在点击按钮后出现的弹窗现在时在屏幕的下方,这也是与alert的一大不同。
对于alert和confirmationdialog,一般来说:
- **ConfirmationDialog:**主要用于获取用户的确认,通常用于破坏性操作或需要用户仔细考虑的操作。
- **Alert:**主要用于向用户传达信息或提供操作,例如显示错误消息或提供重试选项。
通过了解它们的差异和何时使用它们,您可以创建高效且用户友好的界面。
6.contextMenu
前面我们介绍了两个弹窗UI,下面我们再来介绍一个ContextMenu,也是一个界面交互UI。不同的是它不会固定出现于屏幕的中间或者下方,而是出现在你设计的元素旁边。
下面看一个简单示例:
现在我们设计了一个小图标,并在图标的设计中加上了contextMenu,我们现在点击并按住该图标。
可以看到,我们的文本从图标上出现,这是一个很好的交互设计。
现在让我们添加上可点击的Button,来让该图标实现背景色的变化,实现一个真正的交互:
首先创造一个变量
接着写入三个按钮,并对每个按钮进行action的定义和文本设计。
这样就完成了一个简单的UI设计。
在contexMenu中默认的触发方式是长按进行触发(现在默认是0.2s)。如果不想长按触发,我们可以修改contextMenu的触发方式,使用interactionKind修改器。
此外,我们甚至可以设置长按的触发时间(初始默认的触发时长为0.2s):
7.TextField
在进行信息确认或注册登记时,我们往往需要用户写入文本并提交一些东西,SwifUI中的TextField就为我们提供了一个非常易于实现的文本输入框,可以让用户实际输入并提交文本的方法。
下面我们来看基本用法:
可以看到TextField的使用格式非常多,这里我们只介绍最基本的第二个。
创建一个字符串类型,并进行文本的绑定,并加上内置的标题,这样一个简单的文本框就完成了。
对于文本框,我们可以限定输入的键盘类型:
.default
:默认键盘.asciiCapable
:支持 ASCII 字符的键盘.numbersAndPunctuation
:支持数字和标点的键盘.URL
:支持 URL 的键盘.numberPad
:数字键盘.phonePad
:电话键盘.emailAddress
:电子邮件键盘.decimalPad
:小数键盘.twitter
:Twitter 键盘.webSearch
:网络搜索键盘
可以根据你的需要进行自定义。
下面我们将文本框进行一定的润色,并设计简单的UI界面进行数据收集。
首先我们对文本框进行设计调整
现在我们输入的字体是红色,且文本框变为灰色,可以更好看清文本框。
接下来我们设计一个存数据的按钮:
- 首先设计一个存数据的数组
- 接着设计一个循环遍历存入数组中的每个元素
id:\self 是为数组中的每个元素创建一个对应的id
- 接着设计一个函数来进行数组的添加
- 最后设计按钮
这样我们就完成了一个可以收集数据的UI设计。
下面是已经收集的数据。
因为有时我们对数据要进行一定的筛选,不是所有的数据都可以被我们存入数组中,这时我们可以设计一个Bool函数来对数据进行筛选。
下面看一个示例:
我们设置输入的数据长度要大于等于三时为true,反之为false。
这时,一个关于数据长度的限制设计就完成了。
再进一步,我们设计改变按钮的颜色来确定数据能否存入数组中,并在数据不能存入时将按钮禁用。
来看这两段代码,分别实现了改变按钮颜色和禁用按钮的功能,我们一一解释
第一段代码运用了三元运算符,判断在textIsAppropriate()为true时变蓝色,为false时变灰色。
第二段代码使用了disabled修饰符,它接收的是一个bool变量,数据为true时会禁用按钮使得按钮变为灰色(注意即使我们没写上面变灰的代码按钮仍会变灰)
这样我们就完成了一个简单的带有限制的数据收集UI设计。
8.TextEditor
TextEditor和TextField非常的相似,都是给与用户输入的文本控件。不同的是TextField只能用于输入一行的情况,假如用户有输入多行的需求,这时我们就会使用TextEditor。
下面看基本使用:
我们创建一个TextEditor,输入括号时可以查看它的基本语法,下面我们来演示第二种需要绑定的方法。
创建一个字符串类型的变量,对其进行绑定,然后我们像之前一样创建一个按钮,并将按钮和TextEditor放入同一个VStack中。
我们发现按钮被放在了屏幕的底部,但我们中间却没有spacer()等元素对两者进行隔开,为什么会这样?
我们为Vstack添加一个背景色,可以看到原来是TextEditor占用了绝大部分空间,这是它的一大特性:占用尽可能大的空间。
如果我们不想其占用过多的空间,我们可以对其使用frame修饰器来进行限制。
另外,TextEditor具有一个特性:可滚动性。即如果文本超过可用空间,TextEditor 会自动滚动。