Swift UI学习(2)

本文详细介绍了SwiftUI中的SafeArea概念,如何使用ignoresSafeArea控制布局,Button的基本用法和高级定制,@State在状态管理中的作用,以及function和subviews的代码组织。还探讨了如何使用@Binding解决视图间数据共享,ifelse语句的应用,动画和transition的使用方法,以提升UI设计和用户体验。
摘要由CSDN通过智能技术生成

Swift UI学习(2)

1.Safe Area

Safe Area(安全区域)是指不与导航栏、标签栏、工具栏或其他视图控制器提供的视图重叠的内容空间。

在SwfitUI 中,为确保开发者创建的视图都被布局到安全区域当中,SwiftUI 同时提供了一些方法和工具让开发者对安全区域有所控制。

下面是iPhone和ipad的安全区域示意图:

在这里插入图片描述
在这里插入图片描述

注:不同型号上的iPhone和ipad的安全区域可能不同

因为有了Safe Area的存在,我们在进行一些设计时会导致无法铺满整个屏幕,如在进行背景的设计时总会空出一部分的区域,不利于我们进行UI的设计:
在这里插入图片描述

在这里插入图片描述

可以看到哪怕我让框架尽可能的大也仍然没有铺满背景图片。

SwiftUI针对这个情况专门有一个函数ignoresSafeArea(),他可以让我们忽略安全区域,默认情况下是忽略所有的安全区域,我们也可以单独去设计它可以忽略哪些安全区域。其初始定义如下:

@inlinable public func ignoresSafeArea(_ regions: SafeAreaRegions = .all, edges: Edge.Set = .all) -> some View

可以看到,这个函数中含有两个参数,SafeAreaRegionsedges

对于edges,用来指定忽略的安全区域边缘,如:

  • .all:忽略所有安全区域边缘。
  • .top:忽略顶部安全区域边缘。
  • .bottom:忽略底部安全区域边缘。
  • .left:忽略左侧安全区域边缘。
  • .right:忽略右侧安全区域边缘。

对于SafeAreaRegions,指定要忽略的安全区域区域。这对于在安全区域内放置特定类型的视图或内容非常有用。它包含三种划分:

  • container

由设备和用户界面内的容器所定义的安全区域,包括诸如顶部和底部栏等元素。

  • keyboard

与显示在视图内容上的任何软键盘的当前范围相匹配的安全区域。

  • all(默认)

上述两种安全区域划分的合集

下面我们来讲一下使用该函数时可能出现的一些问题,例如刚才的背景,我们在背景的下面加上忽略安全区域,并且想让文字刚好出现在界面的顶部,这时我们将spacer()添加在下面,点击预览:

在这里插入图片描述

在这里插入图片描述

可以看到,我们成功的忽略了安全区域,但坏消息是我们的文字也忽略了安全区域,这将导致我们的文字无法显示在视图上。

为了解决这个问题,我们可以使用一个Zstack()将我们的代码扩起来,并将背景色和忽略函数写在Zstack()上。由于Zstack()的特性(自后往前),我们的文字就会出现在屏幕安全区域顶端。

在这里插入图片描述

2.Button

Button(按钮)顾名思义,就是一个可以点击的按钮,在swiftui中,按钮是十分重要的一环,它可以帮我们做到许多的交互和设计。

先来看看Button的基本使用,一般而言,我们会使用下面两种输入方式.

Button( //标题  , action: //操作 )
前面只能接收字符串,为文本,不能改变样式。
Button(action: {
    // 操作
}) {
    // 按钮样式
}
我们也可以不输入action,这样点击下去的按钮不会执行任何操作。

下面看一个简单的使用,

在这里插入图片描述

我们设置了一个改变标题的按钮,并将标题设置为一个可变的量(@state声明是可变的变量,后面会讲到),点击按钮后改变标题。

在这里插入图片描述

很多时候按钮需要更多样化,来达到美化UI的作用,这时我们就会用到Button的第二种定义,下面设计一个按钮样例:

在这里插入图片描述

3.@State

在 SwiftUI 中,视图是由数据(状态)驱动的。每当视图在创建或解析时,都会为该视图和该视图中使用的状态数据之间创建一个依赖关系,每当状态的信息发生变化,有依赖关系的视图会马上翻译出这些变化并重绘,而@State就是一个联系视图和动态数据之间的一个桥梁。

我们在构建变量时往往需要进行视图的更新,@State的作用就是告诉视图这是一个会改变的量,我们需要去观察它的状态并改变视图。

如果我们只是将一个数据类型修改为var(变量),而不在前面加上@State,会发生以下情况:

  • 变量的值不会被 SwiftUI 追踪,因此当变量值发生变化时,UI 不会自动更新。

  • 尝试访问未被 @State 修饰的变量时,会引发编译器错误

    下面看一个例子:

    在这里插入图片描述

这时swift会跳出以下错误:

在这里插入图片描述

因为我们访问了一个没有@state类型的变量数据,所以编译器认为这是一条不完整的语句。

此外,@State不光能装饰Int,Double等常规的数据类型,@State几乎可以UI中的任何变量,如:Color,Button,font等

4.function和subviews

我们在构建视图时,为了装饰,一个元素可能就要写好几行,这样我们在进行整体设计时,代码会变得非常多。冗长的代码不利于我们的维护和修改,为此我们需要分化代码,这时就会用到function(函数)和subviews(子视图)。

4.1function

对于function,我们可以将需要修改变量状态的类型放在函数中,如我们设计一个按钮,点击按钮会改变背景颜色。
在这里插入图片描述

设计一个按钮的函数:

在这里插入图片描述

然后将action中的语句替换为Buttonchange()即可,而且我们可以通过点击这个函数直接找到对应的位置。

这个代码并没有很好的体现函数的简化,但如果一个按钮中有多个操作或者再遇到类似的操作时,我们可以直接调用函数来完成,

4.2subviews

在视图的创建过程中,我们尽管可以使用函数对代码进行简化,但仍然会显得很冗长,这时我们可以将视图分开,即创建多个子视图,在主视图中只保留子视图的名称即可。

如我们将上面的按钮放入一个子视图中,命名为contentLayer,这时我们只需要在主视图里写上子视图的名字即可自动更新。

在这里插入图片描述

在这里插入图片描述

这时的视图也会更新为刚才我们写在主视图的样子,分子视图的写法可以让我们的代码更有明确性,方便查找和维护。

上面的子视图固然方便,但当我们需要动态的调用子视图时(如将按钮中的数字更换并创造多个类似的按钮)这种时候,我们就需要另一种视图:Extract Subview

在这里插入图片描述

这时我们就创建了一个Extract Subview,这个视图中基本含有和我们主视图一样的元素,因此我们也可以称为第二屏幕,我们可以在里面定义一些新的变量,这时我们再调用这个子视图时,它会要求我们对这些变量进行赋值:

在这里插入图片描述

创建的变量。

在这里插入图片描述

可以看到在主视图中调用这个视图时我们可以对其进行直接的赋值。

注意:视图的名称是可以自定义修改的

在这里插入图片描述

我们可以用此进行重复框架但不同细节的创造,这会大大的提升我们的效率。

5.@Binding

我们前面学习了使用Extract Subview来进行代码的分化,但是使用这个方法时会出现一个问题,下面看一个例子:

在这里插入图片描述

我们将主视图的Button都放入了Extract Subview创建的视图中,但是我们却无法在这个子视图中调用主视图的变量元素,你可以在创建一个和主视图变量同名的变量,但此变量非彼变量。

这是因为Extract Subview的视图不是主视图的直接子视图,当使用 @State 修饰一个变量时,SwiftUI 会创建一个私有存储,该存储与视图及其所有子视图相关联。当子视图从主视图中提取时,它们不再与主视图的私有存储相关联,因此无法访问 @State 定义的变量。

这时我们就需要用到一个@Binding(绑定),该变量会帮助我们把变量进行绑定,进行视图间的共享。

我们将上面的代码进行完善:

在这里插入图片描述

这时我们在主视图的调用中添加了一个$符号,这意味着下面使用@Binding绑定的变量是跟主视图中的backgroundColor变量绑定,且绑定是双向的,@Binding也可以用于非主子视图的绑定,即任意两视图的绑定

注意:一般来说我们绑定的变量名跟主视图的变量名相同,你也可以设置不相同变量名

6.if else 语句

在swift中,我们常用if else 语句来进行条件的判断和执行。在SwiftUI中,我们也常用if else 语句来进行我们所需要的变化。如在Button语句中,我们可以用它来进行判断,在特定条件下会出现特定的图像。

在这里插入图片描述

注:toggle表示bool函数在true和false之间切换,即点一下改变一次。

在这份代码中,我们创建了一个变量showCircle,并用if else 语句来进行按下按钮的判断,如果按下按钮时showCircle为真,那么我们就会出现一个圆形,反之则出现一个矩形。

此外,在条件的判断中,我们可以使用 ||(或) ,&&(且),!(非),以及三元运算符: *”?:“*来进行代码的优化。

下面重点看一下三元运算符,在我们创建视图的过程中,可能存在只有颜色改变而图片的形状和大小不改变(或只有大小变形状不变)类似的例子,这时我们可以使用三元运算符来简化我们的代码。

简化前:
在这里插入图片描述

简化后

在这里插入图片描述

这可以大大优化我们的代码量,提高效率。

7.animation

如果你看了上面的代码并尝试运行它,你会发现在你点击按钮的时候画面是瞬间切换的。尽管有时我们会需要这个瞬间切换,但大多数时候为了更好的体验和美观,我们往往会给这个"转场"添加动画(animation),这会使得我们的画面更具有生动感。

一般而言我们会使用下面两种动画修改器:

  • withAnimation(_: ):应用动画到视图树中所有支持动画的视图。
  • animation(_:, value: ):将动画应用于单个视图或属性。

我们下面使用**withAnimation(_: ) **来修改之前的代码:

在这里插入图片描述

.default表示使用默认的动画模式

这时我们查看视图,在点击按钮时我们可以看到下面两个图形,且它们之间有动画的变化。

在这里插入图片描述

在这里插入图片描述

我们还可以通过其它的设置来达到不同的动画效果。

  • duration(_: ):设置动画持续时间。
  • delay(_: ):设置动画延迟时间。
  • repeatCount(_: ):设置动画重复次数。
  • autoreverse(_: ):设置动画是否自动反转。在它们之间切换时产生动画效果。
  • rotationEffect(_: ):设计点旋转,可以设计切换时的旋转角度。

下面看一个示例:

在这里插入图片描述

我们将刚才的按钮动画修改为永远的重复和一直进行来回翻转(true表示来回翻转,而false则会只“有去无回”的重复) ,这时你点击按钮就会发现动画一直在来回变化。

此外,动画还有一个比较有意思的点是,我们可以限制动画过渡的速度变化情况,如先慢后块还是先快后慢的变化,亦或者是线性的变化。下面看一段代码:

在这里插入图片描述

你可能很难在动画的短促变化中看清这些变化,我们可以通过加长动画的变化时间来更清晰的观察到这些变化,在每段代码的后面加上(duration:_)并加上一个较长的变化时间即可,可自行尝试。

8.transition

在SwiftUI中,transition决定了某个View如何插入到视图栈中,或者如何在视图栈中移除。transition自身并没有任何效果, 需要配合动画一起使用,举个例子:

在这里插入图片描述

在上面这段代码中,我们设计了一个点击就将按钮淡出的transition,可以看到他会之间的消失,为了界面的美化,这时我们就会加上以下代码:

 .animation(.easeInOut)

此外,transition中还有别的修饰方式,一般包括如下选项:

  • **modifier:**用于指定过渡效果的修饰符,例如 .opacity(淡入淡出)、.slide(滑动)和 .scale(缩放)。
  • **duration:**指定过渡动画持续时间的可选参数,以秒为单位。
  • **animation:**指定过渡动画缓动效果的可选参数,例如 .easeInOut(平滑、自然的运动)和 .spring(弹簧效果)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值