SwiftUI:如何不隐藏键盘跳转至下一个TextField?
SwiftUI实现TextField自动跳转至下一个输入框的解决方案
你的代码无法实现跳转的核心问题在于单个Bool类型的FocusState无法区分多个TextField的聚焦状态,同时焦点绑定和切换逻辑也存在错误。以下是纯SwiftUI的修正方案,完全不需要依赖UIKit:
核心问题分析
- 原代码使用
@FocusState private var focused: Bool,只能表示"是否有焦点",无法定位到具体是哪个TextField Stone组件中传递_focused的方式错误,没有正确绑定到父视图的聚焦状态- 输入后的焦点切换逻辑没有关联到对应索引的输入框
修正后的完整代码
ContentView 部分
struct ContentView: View { // 用可选Int类型跟踪当前聚焦的TextField索引 @FocusState private var focusedField: Int? var body: some View { HStack(spacing: 3) { ForEach(0..<10, id: \.self) { index in Stone(focusedField: $focusedField, index: index) } } .padding(.horizontal) // 页面加载时自动聚焦第一个输入框 .onAppear { focusedField = 0 } } }
Stone 组件部分
struct Stone: View { @Binding var focusedField: Int? let index: Int @State private var text: String = "" var body: some View { TextField("", text: $text) .multilineTextAlignment(.center) // 绑定聚焦状态:仅当focusedField等于当前索引时,该TextField获得焦点 .focused($focusedField, equals: index) .background(focusedField == index ? .red : .green) .frame(width: 40, height: 40) .onChange(of: text) { newValue in // 限制输入为单个字符 guard let lastChar = newValue.last else { text = "" return } text = String(lastChar) // 自动跳转到下一个输入框,处理最后一个输入框的边界情况 if index < 9 { focusedField = index + 1 } else { // 最后一个输入框输入完成后,失去焦点 focusedField = nil } } } }
关键改动说明
- 聚焦状态管理:使用
@FocusState var focusedField: Int?替代单个Bool值,通过索引精准控制哪个TextField获得焦点 - 焦点绑定方式:用
focused($focusedField, equals: index)替代原有的focused($focused),实现输入框与索引的一一绑定 - 跳转逻辑简化:输入完成后直接修改
focusedField的值为下一个索引,SwiftUI会自动处理焦点切换,无需手动设置focused = true - 边界处理:增加最后一个输入框的判断,避免越界错误
- 布局优化:移除冗余的
GeometryReader,直接用固定尺寸实现布局,代码更简洁
内容的提问来源于stack exchange,提问作者petomuro
相关产品推荐
相关产品推荐

