前言
本章实例主要为通过@State
,list
显示列表名,通过randomElement
随机选中names item
,和通过动态TextField
动态输入信息,Toggle
开关控制是添加name
还是删除name
demo 效果
展示简单的随机选中姓名和随机删除姓名的功能
步骤
创建项目Pick-a-Pal
显示姓名list
快速创建ios项目:Pick-a-Pal
(点击查看xcode创建项目)
主入口文件ContentView
添加个@State
属性的names用来动态存储"名字"集,通过ForEach
遍历显示
swift
// ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var names: [String] = ["Elisha", "Andre", "Jasmine", "Po-Chun"]
var body: some View {
VStack {
List {
ForEach(names, id: \.self) { name in
Text(name)
}
}
}
.padding()
}
}
#Preview {
ContentView()
}
效果:
动态添加姓名
在页面底部添加TextField
输入框,用来接收输入的姓名
diff
// ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var names: [String] = ["Elisha", "Andre", "Jasmine", "Po-Chun"]
+ @State private var nameToAdd = ""
var body: some View {
VStack {
List {
ForEach(names, id: \.self) { name in
Text(name)
}
}
+ TextField("Add Name", text: $nameToAdd)
+ .onSubmit {
+ names.append(nameToAdd)
+ nameToAdd = ""
+ }
}
.padding()
}
}
#Preview {
ContentView()
}
这里的变量 nameToAdd
用来接收输入变量,通过键盘"回车"键触发onSubmit
方法
当输入内容为空时候"回车"也会添加一条空数据 姓名item
,这里需要对 nameToAdd
进行判空校验
diff
// ContentView.swift
TextField("Add Name", text: $nameToAdd)
.onSubmit {
+ if !nameToAdd.isEmpty{
names.append(nameToAdd)
nameToAdd = ""
+ }
}
输入开头相似的name会被自动更正,这里可以使用autocorrectionDisabled
把该功能关闭
diff
// ContentView.swift
TextField("Add Name", text: $nameToAdd)
+ .autocorrectionDisabled()
开启simulator查看
由于点击TextField
输入框在真机情况下是会有软键盘弹出,为了查看实际效果可以运行在Xcode simulator
上查看
选择头部菜单启动simulator
:Product > Run again.
当启动虚拟机时Xcode
将停止Preview
,这时候可以在Xcode
中关闭Preview
视图步骤:
tip:Debug 区域在XCode
右下方可以通过 view
> Debug Area > Hide Debug Area 进行隐藏
随机选中name
首先选中的name是个变量使用@State
,名称为 pickedName
,当有值时候显示出来
diff
// ContentView.swift
struct ContentView: View {
...
+ @State private var pickedName =""
var body: some View {
VStack {
+ Text(pickedName.isEmpty ? " " : pickedName)
...
}
}
}
这里的?
三元操作符(文档)前端的同学经常会使用到
底部添加触发随机选中name的Button
,使用randomElement()
来随机获取names
中的姓名,当 names
为空时候randomElement()
会返回nil
,这里使用 if ...else来做兼容处理
diff
// ContentView.swift
VStack {
...
+ Button("Pick Random Name") {
+ if let randomName = names.randomElement() {
+ pickedName = randomName
+ } else {
+ pickedName = ""
+ }
+ }
}
输入框与Button
边界不是很好识别,添加个Divider
边界分割线效果
diff
// ContentView.swift
VStack {
...
+ Divider()
Button("Pick Random Name") {
if let randomName = names.randomElement() {
pickedName = randomName
} else {
pickedName = ""
}
}
}
...
随机删除name
上述说明主要是添加name
和随机选中 name
,接下来通过Toggle
开关来控制随机 选中/删除 name
,首先设置开关标识 shouldRemovePickedName
默认为false
diff
// ContentView.swift
struct ContentView: View {
...
+ @State private var shouldRemovePickedName = false
...
Divider()
+ Toggle("Remove when picked", isOn: $shouldRemovePickedName)
....
当 shouldRemovePickedName
为true开启删除name逻辑
diff
// ContentView.swift
VStack {
...
Button("Pick Random Name") {
if let randomName = names.randomElement() {
pickedName = randomName
+ if shouldRemovePickedName {
+ names.removeAll { name in
+ return (name == randomName)
+ }
+ }
} else {
pickedName = ""
}
}
}
其中 removeAll
为数组遍历的一个闭包方法,删除的item返回为 true
的,有点像前端的 filter
用
按钮样式调整
随机选中的Button
样式不够明显,这里使用 buttonStyle
修改下样式
diff
// ContentView.swift
VStack {
...
Button("Pick Random Name") {
...
}
+ .buttonStyle(.borderedProminent)
+ .font(.title2) //增大字号
}
现在按钮是有效果,但是边距太窄,这里通过label
去设定下padding
diff
// ContentView.swift
VStack {
...
- Button("Pick Random Name") {
+ Button{
...
+ }label: {
+ Text("Pick Random Name")
+ .padding(.vertical, 8)
+ .padding(.horizontal, 16) }
...
}
样式调整
- 选中的人添加icon,使用字体图标的
hierarchical
(文档)分等级渲染
diff
// ContentView.swift
VStack {
+ VStack(spacing: 8) {
+ Image(systemName: "person.3.sequence.fill")
+ .foregroundStyle(.tint)
+ .symbolRenderingMode(.hierarchical)
+ Text("Pick-a-Pal")
+ }
+ .font(.title)
+ .bold()
+ }
...
}
2.list边缘使用clipShape
裁剪成圆角
diff
// ContentView.swift
VStack {
...
List {
ForEach(names, id: \.self) { name in
Text(name)
}
}
+ .clipShape(RoundedRectangle(cornerRadius: 8))
...
}
- 选中的
name
字体加粗放大和添加主体颜色.pickedName
:Red 0.345, Green 0.337, Blue 0.812.
(查看如何添加主体颜色)
diff
// ContentView.swift
VStack {
...
Text(pickedName.isEmpty ? " " : pickedName)
+ .font(.title2)
+ .fontWeight(.bold)
+ .foregroundColor(.pickedName)
...
}
最终效果:
总结
本章节主要是对@State
巩固和一些组件和api的用
TextField
输入框组件以及onSubmit
方法Divider
分割线组件Toggle
开关组件.randomElement
该方法用于数组随机获取item.removeAll
该方法用于数组删除,通过遍历当return true
的item 将被删除hierarchical
分级渲染icon
颜色