Focused TextField 最终被 SwiftUI 中的键盘覆盖
Focused TextField ends up covered by the keyboard in SwiftUI
我想要完成的事情
用户一次在一个视图中输入值的 TextField
视图的垂直列表。在文本字段中输入值并按下键盘提交按钮后,焦点将移动到下一个文本字段。
我面临的问题
键盘挡住了活动的文本字段。我希望如果我使用 ScrollView
它会自动滚动到下一个聚焦的文本字段,但事实并非如此。
然后我决定尝试使用 ScrollViewReader
的 ScrollViewProxy
对象滚动到焦点文本字段,这很有效!但不完全是。它滚动到选定的文本字段,但不足以越过键盘。它似乎总是在键盘顶部下方一点点(无论是否有键盘工具栏或自动更正栏或什么都没有)。
这是我调用 proxy.scrollTo(focusedInput)
后文本字段大致结束位置的屏幕截图:
这是我希望它结束的地方:
最小代码示例
struct ContentView: View {
@State var inputsValues: [String]
@FocusState var focusedInput: Int?
init() {
inputsValues = (0..<30).map { _ in "" }
}
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack {
ForEach((0..<inputsValues.count), id: \.self) { i in
TextField("Value", text: $inputsValues[i])
.focused($focusedInput, equals: i)
.submitLabel(.next)
.id(i)
.onSubmit {
if (i + 1) < inputsValues.count {
focusedInput = i + 1
proxy.scrollTo(focusedInput)
} else {
focusedInput = nil
}
}
}
}
}
}.toolbar {
ToolbarItem(placement: .keyboard) {
Text("This is toolbar")
}
}
}
}
在一个闭包中改变两个以上的状态(当它们以某种方式相关或影响一个区域时)处理得不是很好(或不可靠)。解决方法是将它们分开放在不同的处理程序中。
测试 Xcode 13.3 / iOS 15.4
这是主要部分:
VStack {
// ... other code
.onSubmit {
// update state here !!
if (i + 1) < inputsValues.count {
focusedInput = i + 1
} else {
focusedInput = nil
}
}
}
}
.onChange(of: focusedInput) {
// react on state change here !!
proxy.scrollTo([=10=])
}
我想要完成的事情
用户一次在一个视图中输入值的 TextField
视图的垂直列表。在文本字段中输入值并按下键盘提交按钮后,焦点将移动到下一个文本字段。
我面临的问题
键盘挡住了活动的文本字段。我希望如果我使用 ScrollView
它会自动滚动到下一个聚焦的文本字段,但事实并非如此。
然后我决定尝试使用 ScrollViewReader
的 ScrollViewProxy
对象滚动到焦点文本字段,这很有效!但不完全是。它滚动到选定的文本字段,但不足以越过键盘。它似乎总是在键盘顶部下方一点点(无论是否有键盘工具栏或自动更正栏或什么都没有)。
这是我调用 proxy.scrollTo(focusedInput)
后文本字段大致结束位置的屏幕截图:
这是我希望它结束的地方:
最小代码示例
struct ContentView: View {
@State var inputsValues: [String]
@FocusState var focusedInput: Int?
init() {
inputsValues = (0..<30).map { _ in "" }
}
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack {
ForEach((0..<inputsValues.count), id: \.self) { i in
TextField("Value", text: $inputsValues[i])
.focused($focusedInput, equals: i)
.submitLabel(.next)
.id(i)
.onSubmit {
if (i + 1) < inputsValues.count {
focusedInput = i + 1
proxy.scrollTo(focusedInput)
} else {
focusedInput = nil
}
}
}
}
}
}.toolbar {
ToolbarItem(placement: .keyboard) {
Text("This is toolbar")
}
}
}
}
在一个闭包中改变两个以上的状态(当它们以某种方式相关或影响一个区域时)处理得不是很好(或不可靠)。解决方法是将它们分开放在不同的处理程序中。
测试 Xcode 13.3 / iOS 15.4
这是主要部分:
VStack {
// ... other code
.onSubmit {
// update state here !!
if (i + 1) < inputsValues.count {
focusedInput = i + 1
} else {
focusedInput = nil
}
}
}
}
.onChange(of: focusedInput) {
// react on state change here !!
proxy.scrollTo([=10=])
}