如何让@FocusState属性在.sheet中的TextField正常工作?
解决Sheet中@FocusState不触发onChange的问题
问题核心在于Sheet拥有独立的焦点环境,主视图的@FocusState变量无法正确追踪Sheet内部TextField的焦点状态变化。最合理的解决方式是将Sheet内容封装为独立子视图,把@FocusState放在子视图内部管理,或者通过FocusScope让焦点状态和TextField处于同一作用域。
方案一:拆分独立子视图(推荐)
这种方式符合SwiftUI视图组合的设计原则,代码结构更清晰:
struct TestView: View { @State private var sheetIsPresented: Bool = false @State private var userInput: String = "" var body: some View { Button("Hello") { sheetIsPresented = true } .buttonStyle(.borderedProminent) .sheet(isPresented: $sheetIsPresented) { InputSheetView(userInput: $userInput) } } } // 独立的Sheet内容视图 struct InputSheetView: View { @Binding var userInput: String // 在子视图内部定义FocusState,绑定自身焦点环境 @FocusState private var textFieldIsFocused: Bool var body: some View { HStack { Text("Name:") TextField("Enter name", text: $userInput) .focused($textFieldIsFocused) .onChange(of: textFieldIsFocused) { newValue in print("textFieldIsFocused: \(newValue)") } } } }
方案二:使用FocusScope包裹Sheet内容
如果不想拆分视图,可以用FocusScope确保焦点状态和TextField处于同一作用域:
struct TestView: View { @State private var sheetIsPresented: Bool = false @State private var userInput: String = "" @FocusState private var textFieldIsFocused: Bool var body: some View { Button("Hello") { sheetIsPresented = true } .buttonStyle(.borderedProminent) .sheet(isPresented: $sheetIsPresented) { FocusScope { // 用FocusScope包裹Sheet内容 HStack { Text("Name:") TextField("Enter name", text: $userInput) .focused($textFieldIsFocused) .onChange(of: textFieldIsFocused) { print("textFieldIsFocused: \($0)") } } } } } }
两种方案都能让Sheet内的TextField焦点变化正常触发onChange回调,其中拆分独立子视图的方式更利于后续代码维护和扩展。
内容的提问来源于stack exchange,提问作者Ser Pounce
相关产品推荐
相关产品推荐

