iOS – Descartar el teclado al tocar fuera de UITextField

Me pregunto cómo hacer desaparecer el teclado cuando el usuario toca fuera de un UITextField .

Deberá agregar un UITapGestureRecogniser y asignarlo a la vista, y luego llamar a renunciar al primer respondedor en UITextField en su selector.

El código:

En viewDidLoad

 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; [self.view addGestureRecognizer:tap]; 

En dismissKeyboard:

 -(void)dismissKeyboard { [aTextField resignFirstResponder]; } 

(Donde aTextField es el campo de texto que es responsable del teclado)

La versión de Swift 3 se parece a eso

 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:))) self.view.addGestureRecognizer(tapGesture) 

Para descartar el teclado

 func dismissKeyboard (_ sender: UITapGestureRecognizer) { aTextField.resignFirstResponder() } 

Yo aplasté algunas respuestas.

Use un ivar que se inicialice durante viewDidLoad:

 UIGestureRecognizer *tapper; - (void)viewDidLoad { [super viewDidLoad]; tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; tapper.cancelsTouchesInView = NO; [self.view addGestureRecognizer:tapper]; } 

Descartar lo que está actualmente editando:

 - (void)handleSingleTap:(UITapGestureRecognizer *) sender { [self.view endEditing:YES]; } 

Comprueba esto, esta sería la forma más fácil de hacerlo,

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self.view endEditing:YES];// this will do the trick } 

O

Esta biblioteca se encargará de incluir desplazamiento automático de la barra de desplazamiento, espacio de toque para ocultar el teclado, etc.

https://github.com/michaeltyson/TPKeyboardAvoiding

Veo que algunas personas tienen problemas al usar el método UITapGestureRecognizer . La forma más fácil en la que he logrado esta funcionalidad sin dejar intacto el comportamiento de toque de mi botón existente es agregar solo una línea a la respuesta de @Jensen2k:

 [tap setCancelsTouchesInView:NO]; 

Esto permitió que mis botones existentes funcionaran sin usar el método de @Dmitry Sitnikov.

Lea sobre esa property aquí (busque CancelsTouchesInView ): UIGestureRecognizer Class Reference

No estoy seguro de cómo funcionaría con las barras de desplazamiento, ya que veo que algunos tenían problemas, pero es de esperar que alguien más se encuentre con la misma situación que yo.

Es mejor hacer de su UIView una instancia de UIControl (en el constructor de interfaces) y luego conectar su evento dismissKeyboard para dismissKeyboard método de dismissKeyboard . Este método IBAction se verá así:

 - (IBAction)dismissKeyboard:(id)sender { [aTextBox resignFirstResponder]; } 

La versión Swift, esto funciona en combinación con otros elementos (como un UIButton u otro UITextField ):

 override func viewDidLoad() { super.viewDidLoad() let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing)) tapper.cancelsTouchesInView = false view.addGestureRecognizer(tapper) } 

¿Qué tal esto? Sé que esta es una publicación anterior. Podría ayudar a alguien 🙂

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSArray *subviews = [self.view subviews]; for (id objects in subviews) { if ([objects isKindOfClass:[UITextField class]]) { UITextField *theTextField = objects; if ([objects isFirstResponder]) { [theTextField resignFirstResponder]; } } } } 

Esta es una buena solución genérica:

C objective:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } 

Rápido:

 override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { self.view.endEditing(true) } 

Basado en la solución @icodebuster: https://stackoverflow.com/a/18756253/417652

Creo que la manera más fácil (y la mejor) de hacer esto es subclasificar su vista global y usar el hitTest:withEvent para escuchar cualquier toque. Los toques en el teclado no están registrados, entonces hitTest: withEvent solo se invoca cuando toca / desliza / desliza / pellizca … en otro lugar, y luego llama a [self endEditing:YES] .

Esto es mejor que usar touchesBegan porque touchesBegan no se touchesBegan si hace clic en un botón en la parte superior de la vista. Es mejor que UITapGestureRecognizer que no puede reconocer un gesto de desplazamiento, por ejemplo. También es mejor que usar una pantalla tenue porque en una interfaz de usuario compleja y dinámica, no se puede poner una pantalla tenue en todas partes. Además, no bloquea otras acciones, no necesita tocar dos veces para seleccionar un botón afuera (como en el caso de un UIPopover ).

Además, es mejor que llamar a [textField resignFirstResponder] , porque puede tener muchos campos de texto en la pantalla, por lo que esto funciona para todos.

Puede hacer esto usando Storyboard en XCode 6 y superior:

Crea la acción para ocultar el teclado

Agregue esto al archivo de encabezado de la clase utilizada por su ViewController:

 @interface TimeDelayViewController : UIViewController  - (IBAction)dissmissKeyboardOnTap:(id)sender; @end 

A continuación, agregue esto al archivo de implementación del mismo ViewController:

 - (IBAction)dissmissKeyboardOnTap:(id)sender{ [[self view]endEditing:YES]; } 

Esta será ahora una de las ‘Acciones Recibidas’ para su escena del guión gráfico (es decir, ViewController):

enter image description here

Conecte la acción al evento del usuario

Ahora necesita conectar esta acción al gesto del usuario de tocar el teclado.

Importante: debe convertir el ‘UIView’ que está contenido en su guión gráfico en un UIControl , para que pueda recibir eventos. Seleccione la vista desde su jerarquía de escenas del controlador de visualización:

enter image description here

… y cambia su clase:

enter image description here

Ahora arrastre desde el pequeño círculo al lado de la ‘acción recibida’ para su escena, hacia una parte ‘vacía’ de su escena (en realidad está arrastrando la ‘Acción Recibida’ hacia el UIControl). Se le mostrará una selección de eventos a los que puede conectar su acción para:

enter image description here

Seleccione la opción ‘retocar adentro’. Ahora ha enganchado el IBAcción que creó a una acción del usuario tocando el teclado. Cuando el usuario toca el teclado, ahora estará oculto.

(NOTA: Para enganchar la acción al evento, también puede arrastrar desde la acción recibida directamente al UIControl en la jerarquía de View Controllers. Se muestra como ‘Control’ en la jerarquía).

Esta debe ser la forma más fácil de ocultar el teclado tocando afuera:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } 

( ¿Cómo descartar el teclado cuando el usuario toca otra área fuera del campo de texto? )

Swift 4

Configure su UIViewController con este método de extensión una vez, por ejemplo, en viewDidLoad :

 override func viewDidLoad() { super.viewDidLoad() self.setupHideKeyboardOnTap() } 

y el teclado se cerrará incluso tocando en la NavigationBar .

 import UIKit extension UIViewController { /// Call this once to dismiss open keyboards by tapping anywhere in the view controller func setupHideKeyboardOnTap() { self.view.addGestureRecognizer(self.endEditingRecognizer()) self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer()) } /// Dismisses the keyboard from self.view private func endEditingRecognizer() -> UIGestureRecognizer { let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:))) tap.cancelsTouchesInView = false return tap } } 

Si te entendí bien, quieres renunciar al teclado sin tocar el campo de textfield pero no tienes referencia de tu campo de textfield .

Prueba esto;

  • Tome textField global, vamos a llamarlo reftextField
  • Ahora en textFieldDidBeginEditing establece el campo de texto referenciado para

     - (void) textFieldDidBeginEditing:(UITextField *)textField{ reftextField = textField; } 
  • Ahora puede usar felizmente en cualquier botón de reloj, (se recomienda agregar un botón transparente al comenzar la edición)

     - (void)dismissKeyboard { [reftextField resignFirstResponder]; } 
  • O para renunciar al botón hecho prueba esto.

     //for resigning on done button - (BOOL) textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; return YES; } 

Solo para agregar a la lista aquí mi versión de cómo descartar un teclado en el toque externo.

viewDidLoad:

 UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; [self.view addGestureRecognizer:singleTap]; 

En cualquier sitio:

 -(void)handleSingleTap:(UITapGestureRecognizer *)sender{ [textFieldName resignFirstResponder]; puts("Dismissed the keyboard"); } 

Aquí hay muchas respuestas excelentes sobre el uso de UITapGestureRecognizer cuales rompen el UITextField clear (X) de UITextField . La solución es suprimir el reconocedor de gestos a través de su delegado:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]]; BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]]; return !(touchViewIsButton && touchSuperviewIsTextField); } 

No es la solución más robusta, pero funciona para mí.

Si la vista está incrustada en un UIScrollView , puede usar lo siguiente:

 tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; 

El primero animará el teclado fuera de la pantalla cuando se desplace la vista de tabla y el último ocultará el teclado como la aplicación de Mensajes estándar.

Tenga en cuenta que estos están disponibles en iOS 7.0 o superior.

Puede crear una categoría para UiView y anular los toques Comenzar el método de la siguiente manera.

Está funcionando bien para mí. Y es una solución centralizada para este problema.

 #import "UIView+Keyboard.h" @implementation UIView(Keyboard) - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.window endEditing:true]; [super touchesBegan:touches withEvent:event]; } @end 

Versión Swift de la respuesta de @Jensen2k:

 let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard") self.view.addGestureRecognizer(gestureRecognizer) func dismissKeyboard() { aTextField.resignFirstResponder() } 

Un trazador de líneas

 self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:")) 

Usé el ejemplo de Barry para mi nuevo desarrollo. ¡Funcionó muy bien! pero tuve que incluir un cambio leve, necesario para descartar el teclado solo para el campo de texto que se está editando.

Entonces, agregué al ejemplo de Barry lo siguiente:

 - (void) textFieldDidBeginEditing:(UITextField *)textField { _textBeingEdited = textField; } -(void) textFieldDidEndEditing:(UITextField *)textField { _textBeingEdited = nil; } 

Además, cambié el método hideKeyboard de la siguiente manera:

 - (IBAction)hideKeyboard:(id)sender { // Just call resignFirstResponder on all UITextFields and UITextViews in this VC // Why? Because it works and checking which one was last active gets messy. //UITextField * tf = (UITextField *) sender; [_textBeingEdited resignFirstResponder]; } 

Una de las maneras más fáciles y cortas es agregar este código a su viewDidLoad

 [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)]]; 

Swift 4 oneliner

 view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:)))) 

Enviar mensaje resignFirstResponder al texto resignFirstResponder que lo puso allí. Por favor, mira esta publicación para más información.

Esto funciona

En este ejemplo, aTextField es el único UITextField …. Si hay otros o UITextViews, hay un poco más que hacer.

 // YourViewController.h // ... @interface YourViewController : UIViewController /* some subclass of UIViewController */  // <-- add this protocol // ... @end // YourViewController.m @interface YourViewController () @property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer; @end // ... @implementation @synthesize singleTapRecognizer = _singleTapRecognizer; // ... - (void)viewDidLoad { [super viewDidLoad]; // your other init code here [self.view addGestureRecognizer:self.singleTapRecognizer]; { - (UITapGestureRecognizer *)singleTapRecognizer { if (nil == _singleTapRecognizer) { _singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)]; _singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events. } return _singleTapRecognizer; } // Something inside this VC's view was tapped (except the navbar/toolbar) - (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender { NSLog(@"singleTap"); [self hideKeyboard:sender]; } // When the "Return" key is pressed on the on-screen keyboard, hide the keyboard. // for protocol UITextFieldDelegate - (BOOL)textFieldShouldReturn:(UITextField*)textField { NSLog(@"Return pressed"); [self hideKeyboard:textField]; return YES; } - (IBAction)hideKeyboard:(id)sender { // Just call resignFirstResponder on all UITextFields and UITextViews in this VC // Why? Because it works and checking which one was last active gets messy. [aTextField resignFirstResponder]; NSLog(@"keyboard hidden"); } 

Intenté muchas de las respuestas aquí y no tuve suerte. Mi reconocedor de gestos de toque siempre hacía que mis UIButtons no respondieran cuando se tocaban, incluso cuando establecí la propiedad cancelsTouchesInView del reconocedor de gestos en NO.

Esto es lo que finalmente resolvió el problema:

Tener un ivar:

 UITapGestureRecognizer *_keyboardDismissGestureRecognizer; 

Cuando un campo de texto comienza a editarse, configure el reconocedor de gestos:

 - (void) textFieldDidBeginEditing:(UITextField *)textField { if(_keyboardDismissGestureRecognizer == nil) { _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)] autorelease]; _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO; [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer]; } } 

Entonces, el truco está en cómo configurar el método de descartar el teclado:

 - (void) dismissKeyboard { [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01]; } - (void) dismissKeyboardSelector { [self.view endEditing:YES]; [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer]; _keyboardDismissGestureRecognizer = nil; } 

Supongo que hay algo sobre cómo sacar la ejecución de dismissKeyboardSelector de la stack de ejecución de manejo táctil …

 - (void)viewDidLoad { [super viewDidLoad]; UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; [singleTapGestureRecognizer setNumberOfTapsRequired:1]; [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer]; [self.view addGestureRecognizer:singleTapGestureRecognizer]; } - (void)handleSingleTap:(UITapGestureRecognizer *)recognizer { [self.view endEditing:YES]; [textField resignFirstResponder]; [scrollView setContentOffset:CGPointMake(0, -40) animated:YES]; } 

Agregue este código en su archivo ViewController.m :

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } 
 override func touchesBegan(touches: Set, withEvent event: UIEvent?) { if let touch = touches.first{ view.endEditing(true) } } 

En este caso, puede usar ScrollView y agregarse a TextField en ScrollView y quiero. Toque ScrollView y View y luego Descartar el teclado. Traté de crear código de muestra por las dudas. Me gusta esto,

 import UIKit class ViewController: UIViewController { @IBOutlet weak var scrollView: UIScrollView! @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:))) view.addGestureRecognizer(tapGesture) // Do any additional setup after loading the view, typically from a nib. } func tap(gesture: UITapGestureRecognizer) { textField.resignFirstResponder() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } 

Tu guión gráfico Mira eso.

enter image description here

Puede utilizar el método UITapGestureRecongnizer para descartar el teclado haciendo clic fuera de UITextField. Al usar este método cada vez que el usuario haga clic fuera de UITextField, el teclado se descartará. A continuación se muestra el fragmento de código para usarlo.

  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissk)]; [self.view addGestureRecognizer:tap]; //Method - (void) dismissk { [abctextfield resignFirstResponder]; [deftextfield resignFirstResponder]; } 
  • Establecer los campos de texto delegar en vista cargó:

     override func viewDidLoad() { super.viewDidLoad() self.userText.delegate = self } 
  • Agregar esta función:

     func textFieldShouldReturn(userText: UITextField!) -> Bool { userText.resignFirstResponder() return true; }