快捷键
- 资源库:⌘+⇧+L
布局和堆栈
- 默认情况下,图像不可调整大小
- 需要添加一个名为resizable的修饰符(在Modifiers里查找)
-
增大间距
-
添加间隙:
- Views里的spacer
- 框架默认最大(占满整个屏幕),可以自己去inspector里调整Frame
-
-
Frame过大导致有空隙(如下图)
- 可以增加间隙(但它必须已经在V/H/ZStack里了)
- 加阴影:Modifier里的Shadow
-
排列顺序
- 通常将框架Frame放在最前面,偏移放在最后。(否则可能显示不出来效果)
组件和视觉效果
-
如何创建组件,重复多次使用该组件
- ⌘+左键,然后选择Extract Subview
- 在进行下一步前要先命名
- 如命名为CardView,则在最下方自动生成如图
-
组件的Frame设置
- 主卡大小保持不变,设定规模效应(使用修饰符scaleEffect)
-
混合模式 blendMode
- 种类
- Softlight
- Overlay
- Hardlight ——背景很亮的时候使用 e.g.白色
- Multiply
- 对阴影进行操作时,活力很重要——颜色不能太黯淡,除非你就要这样。(更适合iOS的风格)
- 种类
-
iOS13的字体风格
-
大标题:Large titile+Heavy
-
-
分行显示
- 当有长文字时,可以加linelimit来分行显示
-
dock栏(?)
- Frame : 60*6
- CornerRadius : 3
- Opacity : 0.1
-
分隔一个Stack里的物件
- Inspect里的Spacing,设为20
-
填满所有空白的小技巧
- 骆驼式命名法:
.frame(minWidth:0 , maxWidth: .infinity)
动画和状态
- 设置“默认情况下,动画状态是不活动且没有显示的”,如下:
@State var show = false
- 动画开始:action
- 点击开始:
- .onTapGesture
- self.show 是我们的布尔值
- .toggle() 意味着他将在真假间来回切换
- Show ? 10 :0
- .animation()可以加过渡动画
- 括号里选择后,则
- 括号内可以加“duration: 2”,来设定持续多少秒,通常0.5S/0.3S
- Default(默认值)对线性动画很有用,适用于不透明度/模糊等不需要气势的东西。
- 括号里选择后,则
- 点击开始:
手势和事件
1、设置状态viewState
@State var viewState = CGSize.zero
- showState是用于布尔值的ture/false
- viewState是一个定位,我们需要一个由X和Y组成的位置
- 这里的zero意味着这是默认的道具,它被设为0
2、应用手势+检测轨道(track)的位置,然后应用于状态。
(此时已经完成了信息的接受,还未传递出去。)
- 在onTapGesture下面(否则会报错)写上:
.gesture()
- 对于拖拉手势,在括号内加上“DragGesture()”,再在下一行加上修饰符
- 如.onChange{},则需要设置接收值,而从这个值,我们可以接受拖动的位置,所以我们要把这个位置应用到我们的视图状态。
- 写法:
DragGesture()
.onChanged{ value in
self.viewState = value.translation
}
- Translation 和viewState的类型都是CGSiza(按⌥+单击可查看),即具有相同类型的值才可以互相匹配
- 还有在.onChange的下一行写上.onEnded{},使得移动之后自动返回原位置。
3、设置偏移量接受信息
- 偏移量用平移过后的X/Y坐标
- 写法:(因为CGSize有两个值:width/height)
.offset(x: viewState.width, y: viewState.height)
SF符号和道具
如何创建侧边菜单+如何设置菜单动画+如何设置间距/内边距+如何将数据传递到组件里+如何用代码设置SF标志图标+检测屏幕尺寸以便跨设备自适应
-
创建主屏幕
- 右键选择New file,选择SwiftUI View
- 用Image设置SF标志图标:systemName:(记住SF Symbols app里的名字)
- 调整尺寸:找到Symbol Image Scale
- 自定义颜色:foregroundColor
- 添加边框(因为有些图标尺寸不同,设置了之后就都会完美地居中)
- 32*32
- .frame
- 设置一些自定义数据来自定义每一项(通过复制来的每一项)
-
创建一个容器
- Background-cornerRadius-shadow-Spacer(占满上下屏幕)
- -frame(使用min/max来使左右屏幕占满)
- -padding(上下间距)
- -spacing:20(每行之间的间距。在VStack的括号里加)
- -.padding(.trailing,60)(只给行尾留空隙,来留出右边的间隙)
- -spacer(左对齐所有图标。在母模块里操作)
使用数据创建列表
如何从数组中创建列表+如何创建数据模型+如何用它循环这些项并自动执行该列表(不需要复制粘贴4次)
- 在body前输入
-
var menuItems = ["My Account","Billig", "Team", "Sign out”]
- 使用索引(从0开始)
- 前后对比:


-
创建数据模型
- 在代码的最后声明数据模型
-
Identifiable:
- 允许我们不仅使用数据,还可以在以后进行操作
- 至少需要一个可识别的.
- E.g. var id = UUID()
- 循环数据的时候,ID是必要的,有点像key in react
- 任何时候建立数据模型的时候都需要这个作为默认值
- 其他的数据如title/icon
- 在结构菜单之后输入数据
-
let menuData = [ Menu(title: "", icon: ""), Menu(title: "", icon: "") ]
-
- 确保得到了数据(将存储的数据传输到变量上)
- var menu = menuData
- Foreach来循环
-
Foreach(menu){ item in MenuRow(image: item.icon, text: item.title) }
-
(这样使用"item in"就能分别看到每一项(menu是项的集合,item是单独的项))
菜单动画和绑定
菜单动画+运用绑定来把状态传递给组件
-
将菜单移动到顶端
-
用ZStack
- 使得菜单栏下面可以有内容
-
-
创建按键
- Modifier找到button
-
把菜单推到屏幕之外
- offset
- 使用屏幕尺寸
- UIScreen.main.bounds.width/height(加个负就反向)
-
设置动画状态
-
@State var show = false action: {self.show.toggle()}
- 把动画状态变成抵消—显示菜单栏的时候它会是真的(用show ? : )
-
- 设定动画
-
添加点击功能
-
.onTapGesture(count:1, perform: { self.show.toggle() })
-
- 添加3d效果
- 创建组件
- 不见了一些数值
- 对于show状态—使用绑定
- @Binding var show : Bool
- 去主组件把这个状态传递给菜单组件
- 在主组件那边找到对应菜单组件的括号,加上MenuView(show: $show)
- 这意味着他会同步改变
- 从主组件那里听取状态的改变
- 对于show状态—使用绑定
- 不见了一些数值
过渡动画
创建漂浮选择栏按键及屏幕转换
-
输入校准
-
ZStack(alignment: .topLeading)
- 如果有多个ZStack,要放在最外层的(?)m
- 同样的效果可以通过以下这个来实现:
-
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topTrailing)
- 要确保ZStack有Spacer(),否则不会抓到整个屏幕的尺寸
-
滚动内容
创建滚动视图+创建背景阴影
-
投影
- 直接进入样式指南
- 左上角切换到assets
- 做好颜色后 点开右侧的检查器
- 选择颜色 打开属性检查器 直接修改不透明度
- 获得十六进制的颜色值(代码长)
- 设置不透明度
- .shadow,然后选择一个基础色
- 进入检查器 在颜色那栏点击自定义(Custom)
- 直接进入样式指南
- 现在已经拥有了一张卡片
- 拥有父容器之后就可以创建组件了(否则不可以提取子视图)
- 放在HStack下
- 拥有父容器之后就可以创建组件了(否则不可以提取子视图)
- 重复
- ⌘+左键之后点击repeat
- 把HStack嵌入组(Group)中(⌘+左键)
- 类似于占位符
- 把名字换成“ScrollView”
- scrollview内层是HStack就是横线 内层是VStack就是纵向
- ScrollView(. horizontal, showsIndicators: false) 即可左右滑动
- 通过在HStack下使用frame(height: 480)来解决阴影截断问题/Spacer()
模态
如何创建一个内置的模式转换(也适用于iPad)+使用数据填充其余卡片
-
模式转换
- 将元素包装在一个演示按钮中
- 在CourseView上一行加上一些东西
- 1\
-
NavigationView { ScrollView(.horizontal,showsIndicators: false) { HStack { ForEach(0 ..< 3) { item in NavigationLink(destination: ContentView()){ CourseView() }
- 效果:右滑产生一个新界面,这个新界面自带左上角的返回“back”功能
- 2\
- 代码:
-
@State var showContentView: Bool = false var body: some View { ScrollView(.horizontal, showsIndicators: false) { VStack { HStack(spacing: 20) { ForEach(0 ..< 3) { item in Button(action: { self.showContentView = true }) { CourseView() }.sheet(isPresented: self.$showContentView) { ContentView() }
- 效果:从底部划出一个新的界面,原有界面在后面保留
- 括号里可以写上任何目的地(要转到的屏幕)
- 在CourseView上一行加上一些东西
- 将元素包装在一个演示按钮中
-
图标被自动上色
- 去到模块的定义处
- 在image那行的后面加上修饰符:image rendering mode
- 设置为.original
例:
-
前 标题 -
换数据
- 先设置数据模型(前面有提到)
- 再把存储的数据传给变量
- 把Foreach括号里的换成变量的名字
- CoursesView(titile:换成item.title)
-
有时图片太小无法取全宽(full width)
- 两个元素:文字和图片
- 应该有一个完美的框架
- 在image的渲染模式(renderingmode)后面添加一框架修改器(frame)
- 同样可以用这个方法来使文字分行
-
默认模式下image不能随框架缩放
- 让图像可调整大小(image resizable)
- 不能很好地缩放纵横比(可能被拉长)
- 增加纵横比(Aspect Ratio)
- 要在renderingmode的后面
- .fill改成.fit
- 可能会遇到一个图案大一个图案小的情况
- 增加padding(.bottom,??)
- 修改.frame的高度,以免挤占文字的区域
- 不能很好地缩放纵横比(可能被拉长)
- 让图像可调整大小(image resizable)
-
文字好像没有一致的填充
- 原因:frame是手动固定的
- 处理办法:
- 删掉frame
- 用padding(.trailing,50)来实现一样的效果
-
在两个水平模块之间增加空隙
- 在HStack加(spacing:20)
- 在image的渲染模式(renderingmode)后面添加一框架修改器(frame)
模糊背景
iOS的特别之处
- iOS和UIKit里的VisualEffectView在SwiftUI不可用
- UIKit在SwiftUI可用
- 我们将用Swift代码来实现模糊背景的功能
-
创建一个新视图BlurView
- 可以在任何地方使用,尤其是ZStack
- 因为它会占用容器的整个宽度
- 用VStack它则会堆积起来
- 可以在任何地方使用,尤其是ZStack
- 对于IOS12及其之前版本,我们应该在补全选项中选择.dark/.light/.extraLight
- 在ContentView的ZStack里的最前面调用BlurView
- 然后去到Home(主页)
- 确保当你调用ContentView时没有background
- 否则他会取消模糊
- 如果还是看不见
- 把HomeList()放在ZStack的最前面
- 确保当你调用ContentView时没有background
-
在滚动视图的上方加上标题
- 回到HomeList,把ScrollView嵌入到VStack里
- 创建新文本
-
把在整个屏幕上居中的文字调到旁边
- 法一:设置frame(不理想)
- 法二:使用HStack
- 在VStack后面设置间隔(Spacer())
- 这样使用的是屏幕的全宽
- 在VStack后面设置间隔(Spacer())
-
让两个不在同一个模块的文字对齐
- 在inspector里设置left padding:70
- 根据这个已知的数据来做调整
-
在主页上做一些缩放动画
- HomeList的.blur下面紧接着(在animation上方)加入scaleEffection,并设置成0.95
导航视图和列表
iOS自带的导航+创建一个有导航选项的表视图并在SwiftUI里显示+滑动删除/编辑模式+用很舒服的过渡来浏览不同屏幕+从侧面拖动回原来的地方
-
更新列表
- 创建一个新的file
- 在资源库里的”views”里寻找navigation
- Embed in List(嵌入列表中)
- 放置修饰符,让标题变大
- .navigationBarTitle(Text("Updates"))