SwiftUI中如何检测TextEditor的聚焦(点击触发)状态
TextEditor聚焦状态检测实现方案
核心逻辑
SwiftUI 从iOS 15起,通过@FocusState属性包装器统一管理所有输入控件的焦点状态,替代旧版TextField专属的onEditingChanged回调。这套统一的焦点机制可以同时覆盖聚焦、失焦的全触发场景,解决纯点击手势无法检测外部操作导致失焦的问题。
iOS 15+ 原生实现(首选)
直接参照你现有CustomTextField的交互、视觉规则,封装对齐样式的CustomTextEditor:
struct CustomTextEditor: View { @Binding var text: String @State private var isEditing = false @State private var isDisabled = false // 绑定聚焦状态 @FocusState private var editorFocused: Bool init(text: Binding<String>, isDisabled: Bool = false) { self._text = text self.isDisabled = isDisabled } var body: some View { TextEditor(text: $text) .padding(8) // 关联焦点状态,系统自动同步值 .focused($editorFocused) .onChange(of: editorFocused) { newValue in isEditing = newValue } .clipShape(RoundedRectangle(cornerRadius: 4)) .background( RoundedRectangle(cornerRadius: 4) .stroke(isEditing ? Color("Accent") : Color("Gray"), lineWidth: isDisabled ? 0 : 1) ) } }
这套实现的状态感知无遗漏,可覆盖所有触发场景:
- 点击TextEditor区域的进入聚焦动作
- 点击页面空白区域、触发键盘收起的失焦动作
- 同页面其他输入控件抢焦导致的失焦动作
iOS 14及更早版本兼容方案
针对低版本系统,可通过UIViewRepresentable包装原生UITextView实现:
- 在包装器中注册系统自带的编辑状态通知:
UITextView.textDidBeginEditingNotification、UITextView.textDidEndEditingNotification - 在通知回调中同步更新内部的
isEditing状态,和原生实现的感知效果完全一致,无需手动添加点击手势
点击手势方案的缺陷
直接给TextEditor添加点击手势的实现存在天然漏洞:仅能检测用户点击编辑器区域的聚焦动作,无法响应外部交互触发的失焦事件,会导致聚焦状态和实际UI状态长期不同步。
内容的提问来源于stack exchange,提问作者coopersita
相关产品推荐
相关产品推荐

