前言
本章实例主要为通过@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颜色