iOS 16 键盘安全区域未推送更新

Mar*_*ski 14 keyboard ios swiftui ios16

iOS 16 上推送新屏幕时出现奇怪的键盘问题。当您从推送屏幕返回时,键盘安全区域似乎没有更新。

甚至可以在空项目上使用这段代码来重现:

struct ContentView: View {
    
    @State var text = ""
    
    var body: some View {
        NavigationView {
            VStack {
                Spacer()
                NavigationLink {
                    Text("test")
                } label: {
                    Text("Tap me")
                }
                TextField("", text: $text)
                    .textFieldStyle(.roundedBorder)
            }
            .padding()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

重现步骤:

  • 打开键盘
  • 按“点击我”按钮并导航到另一个屏幕
  • 快速返回上一屏幕
  • 键盘被取消了,但是有一个很大的间隙适合键盘尺寸。

还有其他人有类似的问题吗?

fri*_*rin 0

我找到了一个临时的解决方法,它并不漂亮,但它可以删除以前被键盘占用的空白空间。解决方案是从子视图中调用父视图onDisappear,然后在父视图中有一个隐藏的 TextField,该文本字段已获得焦点,但几乎立即失去焦点。

在父视图中添加属性:

@State private var dummyText = ""
@FocusState private var dummyFocus: Bool
Run Code Online (Sandbox Code Playgroud)

并将 TextField 放置在父视图中的某个位置,例如 ZStack 内:

ZStack {
    TextField("", text: $dummyText)
        .focused($dummyFocus)
        .opacity(0.01)

    ... your other layout ...
}
Run Code Online (Sandbox Code Playgroud)

然后使用完成块调用/导航到子视图,如下所示:

ChildView(didDismiss: {
    if #available(iOS 16.0, *) {
        dummyFocus = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            dummyFocus = false
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

在子视图中添加属性:

var didDismiss: () -> Void
Run Code Online (Sandbox Code Playgroud)

并在 child 的 onDisappear 中调用完成块:

.onDisappear {
    didDismiss()
}
Run Code Online (Sandbox Code Playgroud)

onDisappear并且didDismiss()只有在整个交互式向后滑动动画完成后才会被调用。该代码会检查 iOS 16,以便它不会在以前的版本上不必要地执行。