如何实现SwiftUI TextField焦点状态的通用化与可复用?
通用可复用TextField的焦点处理方案
要实现跨项目复用的TextField,同时支持焦点切换,不用依赖特定枚举的话,可以通过给组件传入FocusState布尔绑定和提交动作闭包来实现通用化:
完整的通用TextField组件代码
import SwiftUI struct MyTextField: View { // 文本绑定 @Binding var text: String // 键盘类型 let keyboardType: UIKeyboardType // 提交按钮样式 let submitLabel: SubmitLabel // 焦点状态绑定(由父视图控制) @FocusState.Binding var isFocused: Bool // 提交按钮点击后的回调(可选) let onSubmit: (() -> Void)? var body: some View { TextField("", text: $text) .font(Font.custom(Constants.INTER_MEDIUM, size: 16)) .keyboardType(keyboardType) .foregroundColor(Constants.GRAY_COLOR) .submitLabel(submitLabel) .focused($isFocused) // 绑定焦点状态 .onSubmit { onSubmit?() // 触发父视图定义的提交逻辑 } } // 简化初始化(可选,方便调用) init( text: Binding<String>, keyboardType: UIKeyboardType = .default, submitLabel: SubmitLabel = .done, isFocused: FocusState.Binding<Bool>, onSubmit: (() -> Void)? = nil ) { self._text = text self.keyboardType = keyboardType self.submitLabel = submitLabel self._isFocused = isFocused self.onSubmit = onSubmit } } // 示例Constants定义(根据你的实际项目调整) enum Constants { static let INTER_MEDIUM = "Inter-Medium" static let GRAY_COLOR = Color.gray }
父视图中使用示例(实现焦点切换)
struct FocusDemoView: View { @State private var firstText = "" @State private var secondText = "" // 定义两个独立的焦点状态 @FocusState private var isFirstFieldFocused: Bool @FocusState private var isSecondFieldFocused: Bool var body: some View { VStack(spacing: 20) { MyTextField( text: $firstText, keyboardType: .default, submitLabel: .continue, // 键盘显示"继续"按钮 isFocused: $isFirstFieldFocused, onSubmit: { // 点击继续后,切换焦点到第二个TextField isFirstFieldFocused = false isSecondFieldFocused = true } ) .border(.blue, width: isFirstFieldFocused ? 2 : 1) MyTextField( text: $secondText, keyboardType: .default, submitLabel: .done, isFocused: $isSecondFieldFocused, onSubmit: { // 点击完成后收起键盘 isSecondFieldFocused = false } ) .border(.blue, width: isSecondFieldFocused ? 2 : 1) } .padding() .onAppear { // 初始时让第一个TextField获得焦点 isFirstFieldFocused = true } } }
方案优势
- 完全通用:不需要依赖特定枚举类型,父视图可自由定义焦点状态,组件能直接在任意项目复用
- 灵活可控:焦点切换逻辑由父视图完全掌控,组件仅负责响应焦点状态和触发提交事件
- 扩展性强:后续可轻松添加占位符、边框样式等通用配置,不会影响焦点逻辑
内容的提问来源于stack exchange,提问作者Go Fudge YourSelves
相关产品推荐
相关产品推荐

