SwiftUI - 避免键盘挡住视图推入导航栏

5

我有一个视图,其中包含一些文本框。选择顶部的文本框会导致键盘避让,将所有内容推上去以保持底部的文本框可见。在这种情况下,它会将“Input 1”文本推到导航栏上面的顶部文本框中,将其隐藏。

struct Settings: View {
    @State private var input1: String = ""
    @State private var input2: String = ""
    @State private var input3: String = ""
    @State private var input4: String = ""
    @State private var input5: String = ""
    
    init() {
        let coloredAppearance = UINavigationBarAppearance()
        coloredAppearance.configureWithTransparentBackground()
        coloredAppearance.backgroundColor = .gray

        UINavigationBar.appearance().standardAppearance = coloredAppearance
        UINavigationBar.appearance().compactAppearance = coloredAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
    }
    
    var body: some View {
        NavigationView {
            VStack(spacing: 16) {
                Group {
                    VStack {
                        Text("Input 1")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input1)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Group {
                    VStack {
                        Text("Input 2")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input2)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Group {
                    VStack {
                        Text("Input 3")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input3)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Group {
                    VStack {
                        Text("Input 4")
                            .frame(maxWidth: .infinity, alignment: .leading)
                        TextField("", text: $input4)
                            .disableAutocorrection(true)
                            .padding()
                            .overlay(RoundedRectangle(cornerRadius: 5).stroke(.gray))
                    }
                }
                Spacer()
            }
            .navigationBarTitle("Header", displayMode: .inline)
        }
        .ignoresSafeArea()
    }
}

没有键盘

有键盘

有没有办法防止这种情况?我尝试过使用空白符,但没有成功。虽然这可能会使文本可见,但当键盘未打开时,它会在导航栏和文本之间创建一个空间。我还尝试了对ignoresSafeArea(.keyboard)进行更改。

理想情况下,如果选择了顶部文本字段,则键盘应覆盖底部文本字段,而不会推动任何内容。我只希望在必要时将内容向上推以保持当前选定的文本字段可见。有谁知道如何做到这一点吗?先感谢您。


1
尝试将您的VStack包装在ScrollView中,然后在Textfields上添加.ignoresSafeArea(.keyboard)。 - newb
不要忽略SafeArea。这是你应该尊重的安全区域(底部包括键盘)。你的视图及其所有父视图都应该遵守此规定。 - Leo Dabus
你找到解决办法了吗? - Fitzgerald Afful
1个回答

0
我从一个名叫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)

在UIHostingController子类的初始化器中调用该代码。我可能会将其包装在UIHostingController扩展或其他地方的函数中。
希望这能帮到你!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接