【问题标题】:Press return key "without" dismissing software keyboard - SwiftUI按返回键“不”关闭软件键盘 - SwiftUI
【发布时间】:2020-05-07 23:33:45
【问题描述】:

我想创建一个 TextField,可以在 same 字段中快速输入多个字符串项目,方法是输入项目,然后点击 return 到添加它。

我已经有了添加功能,但是我不想在每次将项目添加到列表时在点击返回时关闭键盘,因为这对于用户每次点击文本字段以进行操作来说很麻烦把键盘拿回来。

如果可能的话,我正在寻找一个纯 SwiftUI 解决方案

我有什么:

import SwiftUI

struct StackOverflowSubmissions: View {

   @State var item: String = ""
   var body: some View {

      TextField("Enter item...", text: $item, onCommit: {

         // Add item to CoreData database

      })
         .textFieldStyle(RoundedBorderTextFieldStyle())
         .padding(5)
         .background(Color(.gray))
         .cornerRadius(10)
         .padding()
    }
}

struct StackOverflowSubmissions_Previews: PreviewProvider {
    static var previews: some View {
        StackOverflowSubmissions()
    }
}


【问题讨论】:

  • 您是否尝试过实现文本字段委托方法?
  • 我不太熟悉,因为我在不熟悉委托模式等的情况下直接进入了 SwiftUI,所以有时像这样让我很痛苦!我已经用 UIViewRepresentable 制作了一个自定义文本字段视图,但是让事情诚实地工作是一件很痛苦的事情。如果可能的话,只是希望有一个简单的面向未来的 SwiftUI 解决方案。
  • 没有纯粹的SwiftUI 解决方案,但如果您愿意,我可以使用UITextViewUIViewRepresentable 提供更好的解决方案,这对SwiftUI 来说是完全好的。谢谢
  • 那太棒了!
  • 您找到解决方案了吗?

标签: ios swift swiftui textfield


【解决方案1】:

这里是CustomTextField,它不会最小化键盘,而是聚焦下一个CustomTextView。这个过程一直持续到当前的CustomTextField 是最后一个CustomTextField

struct CustomTextField: UIViewRepresentable {
    @Binding var text: String // String value of the TextView
    let placeholder: String // Placeholder Text
    let keyboardType: UIKeyboardType // Keypad layout type
    let tag: Int // Tag to recognise each specific TextView
    var commitHandler: (()->Void)? // Called when return key is pressed

    init(_ placeholder: String, text: Binding<String>, keyboardType: UIKeyboardType, tag: Int, onCommit: (()->Void)?) {
        self._text = text
        self.placeholder = placeholder
        self.tag = tag
        self.commitHandler = onCommit
        self.keyboardType = keyboardType
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextField {
        // Customise the TextField as you wish
        let textField = UITextField(frame: .zero)
        textField.keyboardType = self.keyboardType
        textField.delegate = context.coordinator
        textField.backgroundColor = UIColor(white: 0.0, alpha: 0.025)
        textField.layer.borderWidth = 0.5
        textField.layer.borderColor = UIColor.tertiaryLabel.cgColor
        textField.font = UIFont.systemFont(ofSize: 16.0, weight: .light)
        textField.layer.cornerRadius = 6
        textField.isUserInteractionEnabled = true
        textField.text = text
        textField.textColor = UIColor.lightGray
        textField.tag = tag
        textField.placeholder = placeholder

        // For left inner padding
        let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: 120))
        textField.leftView = paddingView
        textField.leftViewMode = UITextField.ViewMode.always

        return textField
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = self.text
        uiView.setContentHuggingPriority(.init(rawValue: 70), for: .vertical)
        uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
    }

    class Coordinator : NSObject, UITextFieldDelegate {

        var parent: CustomTextField

        init(_ uiTextView: CustomTextField) {
            self.parent = uiTextView
        }

        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

            if let value = textField.text as NSString? {
                let proposedValue = value.replacingCharacters(in: range, with: string)
                parent.text = proposedValue as String
            }
            return true
        }

        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            if let nextTextField = textField.superview?.superview?.viewWithTag(textField.tag + 1) as? UITextField {
                nextTextField.becomeFirstResponder()
            } else {
                textField.resignFirstResponder()
            }
            return false
        }

        func textFieldDidEndEditing(_ textField: UITextField) {
            parent.commitHandler?()
        }
    }
}

像这样在ContentView 中使用CustomTextView

struct ContentView: View {
    @State var firstName: String = ""
    @State var lastName: String = ""
    @State var email: String = ""

    var body: some View {
        VStack {
            Text("First Name Value: \(firstName)")
            CustomTextField("First Name", text: self.$firstName, keyboardType: .default, tag: 1, onCommit: nil).padding().frame(height: 70)


            Text("Last Name Value: \(lastName)")
            CustomTextField("Last Name", text: self.$lastName, keyboardType: .default, tag: 2, onCommit: {
                    print("Last Name is: \(self.lastName)")
                }).padding().frame(minWidth: 0, maxWidth: .infinity, minHeight: 70, maxHeight: 70)


            Text("Email Value: \(email)")
            CustomTextField("Email", text: self.$email, keyboardType: .emailAddress, tag: 3, onCommit: {
                    print("Email is: \(self.email)")
                }).padding().frame(minWidth: 0, maxWidth: .infinity, minHeight: 70, maxHeight: 70)
        }
    }
}

【讨论】:

  • 非常感谢您写下这一切!然而,我所追求的是一个单一的文本字段,我可以在不消失键盘的情况下按回车键,同时实现我自己的 addItem 函数,因此字符串被添加到 CoreData 数据库中。这对于登录表单等看起来很棒,但它不是正是我所追求的。
猜你喜欢
  • 2014-12-26
  • 2013-01-09
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多