键盘在 SwiftUI 视图中始终位于顶部

Posted

技术标签:

【中文标题】键盘在 SwiftUI 视图中始终位于顶部【英文标题】:Keyboard always on top in SwiftUI View 【发布时间】:2021-02-20 07:14:06 【问题描述】:

我尝试在 SwiftUI 中开发一个测验应用程序。 为此,我希望键盘始终处于激活状态。

现在的问题是,当我在键盘上按回车键时,它消失了,我必须再次单击文本字段。

如何修改文本框,点击后不会消失,或者在此视图中键盘始终处于激活状态。

我使用以下版本:

Xcode:版本 12.4 (12D4e) / ios 版本:14.4

一些来自所需视图的示例代码:

struct Practice: View 

    @Binding var Alpha: Array<String>
    @State private var inputdesc: String = "Answer"
    @State private var placeholder: String = ""
    @State var new = 0
    
var body: some View 


        
            ZStack 
                Color("Background").ignoresSafeArea()

VStack 
            Text(Alpha[new])
                .font(.system(size: 160))

            TextField(inputdesc, text: $placeholder, onCommit: 
    
                               new = Int.random(in: 0..<Alpha.count)
                               placeholder = ""

                            )
                    
                .font(.system(size: 50))
                .autocapitalization(.none)
                .disableAutocorrection(true)
                .multilineTextAlignment(.center)
                .foregroundColor(Color("BackgroundInverse"))
                


【问题讨论】:

【参考方案1】:

你需要使用 UIKit 代理。

这里是演示版代码。

struct NoneDismissTextField: ViewModifier 

    @ObservedObject var coordinator: Coordinator
    private var onCommit: ()->Void
    
    init(onCommit: @escaping ()->Void) 
        self.onCommit = onCommit
        coordinator = Coordinator(onCommit: onCommit)
    
    
    public struct TextFieldView: UIViewRepresentable 
        
        var configure: (UITextField) -> Void
        
        public func makeUIView(context: UIViewRepresentableContext<TextFieldView>) -> UIView 
            let view = UIView(frame: .zero)
            DispatchQueue.main.async 
                if let textField = view.superview?.superview?.subviews[1].subviews[0] as? UITextField 
                    configure(textField)
                
            
            return view
        
        
        public func updateUIView(_ uiView: UIView,
                                 context: UIViewRepresentableContext<TextFieldView>) 
            
        
    
    
    func body(content: Content) -> some View 

        return content
            .background(TextFieldView(configure:  (textField) in
                textField.delegate = self.coordinator
            ))
    

    class Coordinator: NSObject, ObservableObject, UITextFieldDelegate 
        
        private var onCommit: () -> Void
         
        init(onCommit: @escaping ()->Void) 
            self.onCommit = onCommit
        
        
        func textFieldShouldReturn(_ textField: UITextField) -> Bool 
            onCommit()
            return false
        
    

用法

TextField(inputdesc, text: $placeholder)
    .modifier(NoneDismissTextField(onCommit: 
        new = Int.random(in: 0..<Alpha.count)
        placeholder = ""
    ))

已测试:XCode 12.3、iOS 14.3

【讨论】:

应用程序崩溃并出现以下错误:“由于未捕获的异常 'NSRangeException' 而终止应用程序,原因:'*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'” 您能说说您使用的代码版本和操作系统版本吗? Xcode: Version 12.4 (12D4e) / iOS-Version: 14.4 它也因以下代码崩溃:` TextField(inputdesc, text: $placeholder) .modifier(NoneDismissTextField(onCommit: print("Test ") ))` 我使用 XCode 12.3 和 iOS 14.3 工作正常。 iOS 14.4 发生了一些变化。似乎错误在这里view.superview?.superview?.subviews[1].subviews[0] 你可以用这个检查找到文本字段,或者你可以使用github.com/siteline/SwiftUI-Introspect 这个库来查找文本字段。 感谢@Raja 的帮助,但我无法让它工作。

以上是关于键盘在 SwiftUI 视图中始终位于顶部的主要内容,如果未能解决你的问题,请参考以下文章

如何始终在 SwiftUI 中显示键盘

在 SwiftUI 中显示键盘上方的视图 [关闭]

键盘处理 swiftui

SwiftUI 在 ZStack 中不居中

在 iOS 中,如何创建一个始终位于所有其他视图控制器之上的按钮?

如何使表单始终位于任务栏顶部