.keyboardType() 修饰符仅在 iOS 下有用,否则会报错,因此在做跨平台项目时,注意要用 #if os(iOS) 判断。
.numberPad 和 .decimalPad 键盘类型告诉 SwiftUI 显示数字 0 到 9,也可以选择显示小数点,但这并不能阻止用户输入其他值。例如,如果他们有硬件键盘,他们可以输入自己喜欢的内容,如果他们从其他地方复制一些文本,他们就可以将其粘贴到文本字段中,无论文本内有什么内容。不过没关系——当按下回车键时,文本字段会自动过滤掉错误的值。


| Ascii Capable | .keyboardType(.asciiCapable) |
| Numbers and Punctuation | .keyboardType(.numbersAndPunctuation) |
| URL | .keyboardType(.URL) |
| Numpad | .keyboardType(.numberPad) |
| Phonepad | .keyboardType(.phonePad) |
| Name Phonepad | .keyboardType(.namePhonePad) |
| .keyboardType(.emailAddress) | |
| Decimal Pad | .keyboardType(.decimalPad) |
| Twitter 社交媒体 | .keyboardType(.twitter) |
| Web Search | .keyboardType(.webSearch) |
| Ascii Capable Numpad | .keyboardType(.asciiCapableNumberPad) |
在 swiftUI 视图中,如果弹起 keyboard 键盘,现在键盘的上方是大圆角样式的,导致它两个角会露出底部的背景。这里原因是:SwiftUI 默认会把键盘当成一种 safe area,内容区域会避让键盘。Apple 文档里 SafeAreaRegions.keyboard 就是“当前软件键盘覆盖范围对应的 safe area”;ignoresSafeArea 的作用是让某个视图扩展进这些区域。
正确做法是:不要让主内容忽略键盘,只让背景色忽略键盘。
struct EditView: View {
var body: some View {
ZStack {
Color.myBackground
.ignoresSafeArea(.container)
.ignoresSafeArea(.keyboard, edges: .bottom)
content
}
}
}
这样背景可以延伸到键盘后面,而内容仍然正常避让键盘。
// 如果背景是通过修饰符这样写的:
VStack {
content
}
.background(Color.myBackground)
// 那可以改成
VStack {
content
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background {
Color.myBackground
.ignoresSafeArea(.container)
.ignoresSafeArea(.keyboard, edges: .bottom)
}
如果里面是 List / Form,还要注意它们自己有滚动背景,会盖住你的背景。最终结论:
在 SwiftUI 视图中通过 .onAppear{} 在页面出现时激活键盘,似乎键盘弹起的动画特别突然,总是突然一下把整个页面内容顶上去,动画不够自然。其他应用似乎是激活时,内容先顶上去,然后键盘升起来。中间可能有个短暂的延时。
这个可以优化,但不是调“键盘动画本身”,wiftUI 没有公开 API 自定义系统键盘弹出动画曲线。我们能做的是:不要在 onAppear 里立刻聚焦,而是让页面先完成出现动画/布局稳定后,再触发键盘。
推荐改成 .task 延迟一点,不要用 .onAppear{} 。原因是:onAppear 太早。页面刚被插入视图树,导航转场、sheet 转场、safe area 计算、键盘避让几件事可能挤在同一轮更新里,视觉上就会像“突然被顶上去”。
enum Field: Hashable {
case name
}
@FocusState private var focusedField: Field?
var body: some View {
TextField("Name", text: $name)
.focused($focusedField, equals: .name)
.task {
await Task.yield()
try? await Task.sleep(for: .milliseconds(250))
focusedField = .name
}
}
总结:
使用 .submitLabel() 修饰符,可以定制输入框附带键盘的右下角的提交按钮的样式,例如显示成 “Done” 或 “Next”
TextField("Enter your email address", text: $emailAddress)
.textContentType(.emailAddress)
.submitLabel(.join)
onSubmit() 修饰符可以附加到层次结构中的任何视图。使用此修饰符,用户在 TextField 或 SecureField 完成文字输入后,可以选择运行一个指定的方法。
// 例如,我们可以要求用户输入密码,然后在按回车键时运行一些代码:
struct ContentView: View {
@State private var password = ""
var body: some View {
SecureField("Password", text: $password)
.onSubmit {
print("Authenticating…")
}
}
}
使用 onSubmit() 的优点是它可以捕获在其上下文中提交的所有文本值,这使得填写表单变得更容易:
struct ContentView: View {
@State private var username = ""
@State private var password = ""
var body: some View {
Form {
TextField("Username", text: $username)
SecureField("Password", text: $password)
}
.onSubmit {
guard username.isEmpty == false && password.isEmpty == false else { return }
print("Authenticating…")
}
}
}
SwiftUI 允许向键盘添加输入的附加视图,这意味着当用户激活某些文本输入时,我们可以在那里显示自定义按钮。这是通过将 toolbar() 修饰符附加到相应的视图来完成的。创建工具栏项组时,使用 .keyboard 位置将此工具栏附加到键盘,如下所示:
struct ContentView: View {
@State private var name = "Taylor"
var body: some View {
TextField("Enter your name", text: $name)
.textFieldStyle(.roundedBorder)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
// 里面是具体视图的内容
Button("Click me!") {
print("Clicked")
}
}
}
}
}
// 这个工具栏实际上是放置 “隐藏键盘” 按钮的好地方:
struct ContentView: View {
@State private var name = "Taylor Swift"
@FocusState var isInputActive: Bool
var body: some View {
NavigationStack {
TextField("Enter your name", text: $name)
.textFieldStyle(.roundedBorder)
.focused($isInputActive)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
isInputActive = false
}
}
}
}
}
}