SwiftUI - 键盘避免将内容推入导航栏

Aus*_*Chu 5 ios swift swiftui

我有一些文本字段的视图。选择顶部文本字段会导致键盘避免将所有内容向上推以保持底部文本字段可见。在本例中,它将顶部文本字段上方的“输入 1”文本推入导航栏,将其隐藏。

\n
struct Settings: View {\n    @State private var input1: String = ""\n    @State private var input2: String = ""\n    @State private var input3: String = ""\n    @State private var input4: String = ""\n    @State private var input5: String = ""\n    \n    init() {\n        let coloredAppearance = UINavigationBarAppearance()\n        coloredAppearance.configureWithTransparentBackground()\n        coloredAppearance.backgroundColor = .gray\n\n        UINavigationBar.appearance().standardAppearance = coloredAppearance\n        UINavigationBar.appearance().compactAppearance = coloredAppearance\n        UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance\n    }\n    \n    var body: some View {\n        NavigationView {\n            VStack(spacing: 16) {\n                Group {\n                    VStack {\n                        Text("Input 1")\n                            .frame(maxWidth: .infinity, alignment: .leading)\n                        TextField("", text: $input1)\n                            .disableAutocorrection(true)\n                            .padding()\n                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))\n                    }\n                }\n                Group {\n                    VStack {\n                        Text("Input 2")\n                            .frame(maxWidth: .infinity, alignment: .leading)\n                        TextField("", text: $input2)\n                            .disableAutocorrection(true)\n                            .padding()\n                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))\n                    }\n                }\n                Group {\n                    VStack {\n                        Text("Input 3")\n                            .frame(maxWidth: .infinity, alignment: .leading)\n                        TextField("", text: $input3)\n                            .disableAutocorrection(true)\n                            .padding()\n                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))\n                    }\n                }\n                Group {\n                    VStack {\n                        Text("Input 4")\n                            .frame(maxWidth: .infinity, alignment: .leading)\n                        TextField("", text: $input4)\n                            .disableAutocorrection(true)\n                            .padding()\n                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))\n                    }\n                }\n                Spacer()\n            }\n            .navigationBarTitle("Header", displayMode: .inline)\n        }\n        .ignoresSafeArea()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

不带键盘

\n

带键盘

\n

有人有办法防止这种情况吗?我尝试过垫片但没有成功。虽然这可能会使文本保持可见,但当键盘未打开时,它会在导航栏和文本之间创建一个空间。我也尝试过弄乱 \xc2\xa0 ignoresSafeArea(.keyboard)。

\n

理想情况下,如果选择顶部文本字段,键盘应覆盖底部文本字段,而不向上推任何内容。我只想在必要时上推内容以保持当前选定的文本字段可见。有人有办法做到这一点吗?提前致谢。

\n

Rob*_*ber 1

我从Peter Steinberger的博客文章中找到了解决方案。不幸的是,没有一个原生 API 可以解决这个问题,所以你必须使用一些技巧来阻止 SwiftUI 中的键盘避免。我已经测试了代码并且它有效!当键盘显示时,内容保持不变。

        guard let viewClass = object_getClass(view) else { return }

        let viewSubclassName = String(cString: class_getName(viewClass)).appending("_IgnoresKeyboard")
        if let viewSubclass = NSClassFromString(viewSubclassName) {
            object_setClass(view, viewSubclass)
        }
        else {
            guard let viewClassNameUtf8 = (viewSubclassName as NSString).utf8String else { return }
            guard let viewSubclass = objc_allocateClassPair(viewClass, viewClassNameUtf8, 0) else { return }

            if let method = class_getInstanceMethod(viewClass, NSSelectorFromString("keyboardWillShowWithNotification:")) {
                let keyboardWillShow: @convention(block) (AnyObject, AnyObject) -> Void = { _, _ in }
                class_addMethod(viewSubclass, NSSelectorFromString("keyboardWillShowWithNotification:"),
                                imp_implementationWithBlock(keyboardWillShow), method_getTypeEncoding(method))
            }
            objc_registerClassPair(viewSubclass)
            object_setClass(view, viewSubclass)
Run Code Online (Sandbox Code Playgroud)

在 UIHostingController 子类的初始化程序中调用该代码。我可能会将它包装在 UIHostingController 扩展或其他东西中的函数中。

希望这可以帮助!