有没有办法在 SwiftUI 中为 TextField 设置 inputView?

Sav*_*mex 10 swift swiftui

我想将选择器设置为 TextField 的 inputView,我可以仅使用 SwiftUI 来完成,还是必须在框架集成的帮助下使用 UIKit 组件?

UIKit 中的代码示例:

textField.inputView = UIPickerView()
Run Code Online (Sandbox Code Playgroud)

我想做同样的事情,但使用 SwiftUI 的 TextField

rob*_*off 5

从 Xcode 11.4 开始,SwiftUITextField不具有inputViewUITextField.

UITextField您可以通过将 UIKit 桥接到 SwiftUI 以及将 SwiftUI 桥接到UIKit 来解决此问题Picker。您需要设置文本字段的inputViewController属性而不是其inputView属性。

桥接到UITextFieldSwiftUI

用于UIViewRepresentable将 包装UITextField在 SwiftUI 中View。由于您创建了UITextField,您可以将其inputViewController属性设置为UIViewController您创建的 a 。

将 SwiftUI 桥接到PickerUIKit

用于UIHostingController将 SwiftUI 包装PickerUIViewController. 将文本字段设置inputViewController为您的UIHostingController实例。


Ans*_*ngh 5

我使用上述解决方案发现的唯一问题是,每当键盘进入编辑阶段时,就会出现选择器,并且键盘也会随之出现。

所以没有办法隐藏键盘并显示选择器。因此,我编写了一个自定义结构来处理这种行为,类似于我们使用 UITextField inputView 所做的。你可以使用它。这适用于我的用例。

您还可以自定义选择器,以及像我这样的 makeUIView 方法中的文本字段,已经完成了选择器的背景颜色。

 struct TextFieldWithPickerAsInputView : UIViewRepresentable {

      var data : [String]
      var placeholder : String

      @Binding var selectionIndex : Int
      @Binding var text : String?

      private let textField = UITextField()
      private let picker = UIPickerView()

      func makeCoordinator() -> TextFieldWithPickerAsInputView.Coordinator {
           Coordinator(textfield: self)
      }

      func makeUIView(context: UIViewRepresentableContext<TextFieldWithPickerAsInputView>) -> UITextField {
           picker.delegate = context.coordinator
           picker.dataSource = context.coordinator
           picker.backgroundColor = .yellow
           picker.tintColor = .black
           textField.placeholder = placeholder
           textField.inputView = picker
           textField.delegate = context.coordinator
           return textField
      }

      func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<TextFieldWithPickerAsInputView>) {
           uiView.text = text
      }

      class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate , UITextFieldDelegate {

           private let parent : TextFieldWithPickerAsInputView

           init(textfield : TextFieldWithPickerAsInputView) {
                self.parent = textfield
           }

           func numberOfComponents(in pickerView: UIPickerView) -> Int {
                return 1
           }
           func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
                return self.parent.data.count
           }
           func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
                return self.parent.data[row]
           }
           func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
                self.parent.$selectionIndex.wrappedValue = row
                self.parent.text = self.parent.data[self.parent.selectionIndex]
                self.parent.textField.endEditing(true)

           }
           func textFieldDidEndEditing(_ textField: UITextField) {
                self.parent.textField.resignFirstResponder()
           }
     }
 }
Run Code Online (Sandbox Code Playgroud)

您可以将其用作:-

 struct ContentView : View {

      @State var gender : String? = nil
      @State var arrGenders = ["Male","Female","Unknown"]
      @State var selectionIndex = 0

      var body : some View {
          VStack {
                   TextFieldWithPickerAsInputView(data: self.arrGenders, placeholder: "select your gender", selectionIndex: self.$selectionIndex, text: self.$gender)
         }
     }
 }
Run Code Online (Sandbox Code Playgroud)