代码之家  ›  专栏  ›  技术社区  ›  Barrrdi

防止TextField的键盘在[Return]后被解除,但也需要检测[Return]keypress

  •  0
  • Barrrdi  · 技术社区  · 2 年前

    简言之,当你添加一个条目,点击[Return],然后可以立即添加下一个条目时,我试图实现Reminders.app的交互(即键盘不会关闭,但只有当你在空行上点击[Return]时才会关闭)。

    如果不是因为这个问题,这将是直截了当的: how can I keep the keyboard opened with @FocusState with SwiftUI without a bounce? (键盘在[返回]后反弹)。

    我考虑了很多解决方案,但是 the cleanest to keep the keyboard up is to leverage introspect :

    class TextFieldKeyboardBehavior: UIView, UITextFieldDelegate {
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            return false
        }
    }
    
    struct TestView: View {
        
        @State var text: String = ""
    
        var textFieldKeyboardBehavior = TextFieldKeyboardBehavior()
        
        var body: some View {
            VStack {
                TextField("Title", text: $text)
                    .introspect(.textField, on: .iOS(.v17)) {
                      $0.delegate = textFieldKeyboardBehavior
                    }
                    .onSubmit {
                       // code
                    }
            }
        }
    }
    

    现在,这种方法的(大!)问题是 onSubmit 永远不会接到电话。如果我添加 onChange 修饰符,它在每次按下时都会被调用,但我不相信在这里观察值的变化可以可靠地检测出何时是真正关闭键盘的正确时刻。我知道我有效地禁用了[返回]功能,所以这种行为应该不会令人惊讶,但我想知道是否有另一种方法可以利用内省和 TextField 这启用了Im所追求的:1)键盘不会在[Return]上消失,2)[Return'总是被检测到。

    0 回复  |  直到 2 年前
        1
  •  0
  •   0x1801CE    2 年前

    以下是我使用@FocusState得出的结果。在TextField中输入文本,然后点击return。.onSubmit()将添加另一个TextField并在不忽略键盘的情况下转移其焦点。如果TextField为空,则在点击return时键盘将关闭。

    import SwiftUI
    
    struct TextView: View {
        @State private var textFields: [String] = [""]
        @FocusState private var focusField: Int?
        
        var body: some View {
            VStack {
                ForEach(0..<textFields.count, id: \.self) { index in
                    TextField("Enter text", text: $textFields[index])
                        .padding()
                        .focused($focusField, equals: index)
                        .onSubmit {
                            if !textFields[index].isEmpty {
                                textFields.append("")
                                focusField = textFields.count - 1
                            }
                        }
                }
            }
        }
    }
    
        2
  •  0
  •   Orackle    2 年前

    您必须手动将操作传递给新的代理。 .onSubmit不起作用,因为您用自己的代理替换了原始代理

        3
  •  0
  •   Dean L    2 年前

    我通过将通常在.onSubmit中执行的任何操作传递给UITextFieldDelegate来解决此问题:

    class TextFieldDelegate: NSObject, UITextFieldDelegate {
        
        var shouldReturn: (() -> Bool)?
        
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            
            if let shouldReturn = shouldReturn {
                return shouldReturn()
            }
            else {
                return true
            }
        }
    }
    

    然后在我们的SwiftUI视图中:

    import Introspect
    
    struct TestView: View {
        
        enum FocusedField {
            case username, password
        }
        
        @State private var username: String = ""
        @State private var password: String = ""
        
        var usernameFieldDelegate = TextFieldDelegate()
        var passwordFieldDelegate = TextFieldDelegate()
        
        @FocusState private var focusedField: FocusedField?
        
        var body: some View {
            
            VStack {
                
                TextField(text: $username)
                    .focused($focusedField, equals: .username)
                    .introspectTextField(customize: { textField in
                        
                        usernameFieldDelegate.shouldReturn = {
                            
                            if usernameIsValid() {
                                focusedField = .password
                            }
                            
                            return false
                        }
                        
                        textField.delegate = usernameFieldDelegate
                    })
                
                SecureField(text: $password)
                    .focused($focusedField, equals: .password)
                    .introspectTextField(customize: { textField in
                        
                        passwordFieldDelegate.shouldReturn = {
                            validateAndProceed()
                            
                            return false
                        }
                        
                        textField.delegate = passwordFieldDelegate
                    })
            }
        }
        
        func usernameIsValid() -> Bool {
            return true
        }
        
        func validateAndProceed() {}
    }