在滚动视图中,如果我有一个带有文本字段和按钮的 VStack,按键盘上的 Tab 将从文本字段转到后退按钮,然后转到按钮文本字段和后退按钮。从逻辑上讲,顺序是错误的,它应该从文本字段到按钮。如果我删除滚动视图,选项卡将按预期工作
我尝试使用可聚焦的,但没有运气。以及可访问性排序优先级。
示例:
import SwiftUI
@main
struct MyApp: App {
@State var emailAddress = ""
var body: some Scene {
WindowGroup {
ScrollView {
VStack(alignment: .leading) {
TextField("", text: $emailAddress, prompt: Text("prompt"))
.textFieldStyle(.roundedBorder)
.padding()
Button(action: {
print("test")
})
{
Text("Button")
.frame(maxWidth: .infinity)
.foregroundColor(.white)
.padding()
}
.background(Color.blue)
.cornerRadius(10)
.padding()
.frame(maxWidth: .infinity)
}
}
}
}
}
使用@FocusState手动管理焦点
最可靠的修复方法是完全跳过对 SwiftUI 的默认选项卡/焦点排序的依赖,并显式管理哪个视图获得焦点。您可以使用@FocusState(在 iOS 15 / macOS 12 中引入)来做到这一点。
import SwiftUI
struct ContentView: View {
enum Field {
case email, button
}
@FocusState private var focusedField: Field?
@State private var email = ""
var body: some View {
NavigationView {
ScrollView {
VStack(spacing: 20) {
TextField("Email", text: $email)
.textFieldStyle(.roundedBorder)
.focused($focusedField, equals: .email)
// When user presses 'return' or 'tab' on keyboard:
.onSubmit {
focusedField = .button
}
Button("Button") {
print("Button tapped")
}
.focused($focusedField, equals: .button)
}
.padding()
}
.onAppear {
// Optionally set initial focus
focusedField = .email
}
.navigationTitle("Focus Demo")
}
}
}
工作原理:
这种方法完全绕过了系统默认的“嘿,那里有一个后退按钮”逻辑。