SwiftUI的Keyboard Toolbar作用域问题及多文本框独立工具栏实现方法
问题结论
这个现象属于SwiftUI的预期行为。toolbar修饰符的作用域是它所属的整个视图层级,而非绑定到添加修饰符的单个输入控件上。只要当前激活的输入控件处于toolbar所在的视图层级范围内,定义的键盘工具栏就会自动显示,这就是你给第一个TextField加的工具栏会在第二个TextField激活时也出现的原因。
实现独立键盘工具栏的方案
有两种常用的实现方式:
方案1:通过FocusState跟踪聚焦状态动态渲染
使用@FocusState记录当前激活的输入框,在全局toolbar中根据聚焦状态切换不同的工具栏内容:
struct ContentView: View { @State private var first = "" @State private var second = "" // 跟踪当前聚焦的输入框 @FocusState private var focusedField: Field? enum Field: Hashable { case first, second } var body: some View { VStack { TextField("First", text: $first) .focused($focusedField, equals: .first) TextField("Second", text: $second) .focused($focusedField, equals: .second) } .toolbar { ToolbarItem(placement: .keyboard) { // 根据当前聚焦的字段显示不同工具栏 switch focusedField { case .first: Button("Test") { } case .second: Button("另一个按钮") { } case nil: EmptyView() } } } } }
方案2:拆分视图隔离toolbar作用域
将每个TextField和对应的toolbar封装到独立的子视图中,利用子视图的作用域隔离实现工具栏独立:
struct ContentView: View { @State private var first = "" @State private var second = "" var body: some View { VStack { FirstTextField(text: $first) SecondTextField(text: $second) } } } // 第一个输入框独立子视图 struct FirstTextField: View { @Binding var text: String @FocusState private var isFocused: Bool var body: some View { TextField("First", text: $text) .focused($isFocused) .toolbar { // 仅当前子视图内的输入框激活时显示 ToolbarItem(placement: .keyboard) { Button("Test") { } } } } } // 第二个输入框独立子视图 struct SecondTextField: View { @Binding var text: String @FocusState private var isFocused: Bool var body: some View { TextField("Second", text: $text) .focused($isFocused) .toolbar { ToolbarItem(placement: .keyboard) { Button("SecondAction") { } } } } }
内容的提问来源于stack exchange,提问作者Marcus Rossel
相关产品推荐
相关产品推荐

