Saltar al contenido

Extienda el teclado SwiftUI con botón personalizado

Solución:

Resolvió el problema utilizando el protocolo UIRepresentable

struct TestTextfield: UIViewRepresentable {
    @Binding var text: String
    var keyType: UIKeyboardType
    func makeUIView(context: Context) -> UITextField {
        let textfield = UITextField()
      textfield.keyboardType = keyType
        let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
        let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textfield.doneButtonTapped(button:)))
        toolBar.items = [doneButton]
        toolBar.setItems([doneButton], animated: true)
        textfield.inputAccessoryView = toolBar
        return textfield
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
        
    }
}

extension  UITextField{
    @objc func doneButtonTapped(button:UIBarButtonItem) -> Void {
       self.resignFirstResponder()
    }

}

Usar en la vista de contenido

struct ContentView : View {
    @State var text = ""
    
    var body: some View {
        TestTextfield(text: $text, keyType: UIKeyboardType.phonePad)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50)
            .overlay(
                RoundedRectangle(cornerRadius: 16)
                    .stroke(Color.blue, lineWidth: 4)
        )
    }
}

Si hay un problema con @Binding implementar la clase Coordinator que se ajusta a UITextFieldDelegate. Esto permitirá que uno pueda personalizar el TextField aún más si es necesario.

struct DecimalTextField: UIViewRepresentable {
     private var placeholder: String
     @Binding var text: String

     init(_ placeholder: String, text: Binding<String>) {
        self.placeholder = placeholder
        self._text = text
     } 

     func makeUIView(context: Context) -> UITextField {
        let textfield = UITextField()
        textfield.keyboardType = .decimalPad
        textfield.delegate = context.coordinator
        textfield.placeholder = placeholder
        let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
        let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textfield.doneButtonTapped(button:)))
        toolBar.items = [doneButton]
        toolBar.setItems([doneButton], animated: true)
        textfield.inputAccessoryView = toolBar
        return textfield
     }

     func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
     }

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

     class Coordinator: NSObject, UITextFieldDelegate {
        var parent: DecimalTextField
    
     init(_ textField: DecimalTextField) {
        self.parent = textField
     }
    
     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
         if let currentValue = textField.text as NSString? {
             let proposedValue = currentValue.replacingCharacters(in: range, with: string) as String
             self.parent.text = proposedValue
         }
         return true
     }
   }
 }

¡Lo hice en 5 líneas usando la biblioteca SwiftUI-Introspect! Tuve el problema de que el campo de texto representable no reaccionaba de ninguna manera al relleno y al marco. ¡Todo se decidió usando esta biblioteca!

Enlace: https://github.com/siteline/SwiftUI-Introspect

import SwiftUI
import Introspect

struct ContentView : View {
@State var text = ""

var body: some View {
    TextField("placeHolder", text: $text)
       .keyboardType(.default)
       .introspectTextField { (textField) in
           let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textField.frame.size.width, height: 44))
           let flexButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
           let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textField.doneButtonTapped(button:)))
           doneButton.tintColor = .systemPink
           toolBar.items = [flexButton, doneButton]
           toolBar.setItems([flexButton, doneButton], animated: true)
           textField.inputAccessoryView = toolBar
        }
}

extension  UITextField {
   @objc func doneButtonTapped(button:UIBarButtonItem) -> Void {
      self.resignFirstResponder()
   }
}

producción

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *