¿Cómo descartar el teclado para UITextView con la tecla de retorno?

En la biblioteca de IB, la introducción nos dice que cuando se presiona la tecla de retorno, el teclado para UITextView desaparecerá. Pero en realidad la tecla de retorno solo puede actuar como ‘\ n’.

Puedo agregar un botón y usar [txtView resignFirstResponder] para ocultar el teclado.

Pero, ¿hay alguna manera de agregar la acción para la tecla de retorno en el teclado para que no tenga que agregar UIButton ?

UITextView no tiene ningún método que se UITextView cuando el usuario pulsa la tecla de retorno. Si desea que el usuario pueda agregar solo una línea de texto, use un UITextField . UITextView la tecla de retorno y ocultar el teclado para una UITextView no sigue las pautas de la interfaz.

Incluso si desea hacer esto, implemente el método textView:shouldChangeTextInRange:replacementText: de UITextViewDelegate y en esa comprobación, si el texto de reemplazo es \n , oculte el teclado.

Puede haber otras formas, pero no conozco ninguna.

Imaginé que publicaría el fragmento aquí mismo en su lugar:

Asegúrese de declarar compatibilidad con el protocolo UITextViewDelegate .

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if([text isEqualToString:@"\n"]) { [textView resignFirstResponder]; return NO; } return YES; } 

Actualización de Swift 4.0:

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.resignFirstResponder() return false } return true } 

Sé que esto ya se ha respondido, pero realmente no me gusta usar el literal de la cadena para la nueva línea, así que esto es lo que hice.

 - (BOOL)textView:(UITextView *)txtView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if( [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location == NSNotFound ) { return YES; } [txtView resignFirstResponder]; return NO; } 

Actualización de Swift 4.0:

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if (text as NSString).rangeOfCharacter(from: CharacterSet.newlines).location == NSNotFound { return true } txtView.resignFirstResponder() return false } 

Sé que esto ha sido respondido muchas veces, pero aquí están mis dos centavos al respecto.

Encontré las respuestas de samvermette y ribeto realmente útiles, y también el comentario de maxpower en la respuesta del ribeto . Pero hay un problema con esos enfoques. El problema que Matt menciona en la respuesta de Samvermette es que si el usuario quiere pegar algo con un salto de línea dentro, el teclado se escondería sin pegar nada.

Así que mi enfoque es una mezcla de las tres soluciones mencionadas anteriormente y solo verifico si la cadena ingresada es una nueva línea cuando la longitud de la cadena es 1, así que nos aseguramos de que el usuario esté escribiendo en lugar de pegar.

Esto es lo que hice:

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { NSRange resultRange = [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch]; if ([text length] == 1 && resultRange.location != NSNotFound) { [textView resignFirstResponder]; return NO; } return YES; } 

Una forma más elegante es descartar el teclado cuando el usuario toca en algún lugar fuera del marco del teclado.

Primero, configure la vista de su ViewController en la clase “UIControl” en el inspector de identidad en UIBuilder. Mantenga presionada la vista de control en el archivo de encabezado ViewController y vincúlela como una acción con el evento como Touch Up Inside, como:

ViewController.h

 -(IBAction)dismissKeyboardOnTap:(id)sender; 

En el archivo ViewController principal, ViewController.m:

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

Puede requerir un toque doble o toque largo usando técnicas similares. Es posible que necesite configurar su ViewController para ser un UITextViewDelegate y conectar el TextView al ViewController. Este método funciona para UITextView y UITextField.

Fuente: Big Nerd Ranch

EDITAR: También me gustaría añadir que si está utilizando un UIScrollView, la técnica anterior puede no funcionar tan fácilmente a través del Interface Builder. En ese caso, podría usar un UIGestureRecognizer y llamar al método [[self view] endEditing: YES] dentro de él. Un ejemplo sería:

 -(void)ViewDidLoad{ .... UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)]; [self.view addGestureRecognizer: tapRec]; .... } -(void)tap:(UITapGestureRecognizer *)tapRec{ [[self view] endEditing: YES]; } 

Cuando el usuario toca fuera del teclado y no toca un espacio de entrada, el teclado se cerrará.

Agregue este método en su controlador de vista.

Swift :

 func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.resignFirstResponder() return false } return true } 

Este método también puede ser útil para usted:

 /** Dismiss keyboard when tapped outside the keyboard or textView :param: touches the touches :param: event the related event */ override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { if let touch = touches.anyObject() as? UITouch { if touch.phase == UITouchPhase.Began { textField?.resignFirstResponder() } } } 
 -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if([text isEqualToString:@"\n"]) [textView resignFirstResponder]; return YES; } yourtextView.delegate=self; 

También agregue UITextViewDelegate

No te olvides de confirmar el protocolo

SI no agregó if([text isEqualToString:@"\n"]) no puede editar

Hay otra solución al usar con uitextview. Puede agregar la barra de herramientas como InputAccessoryView en “textViewShouldBeginEditing”, y desde este botón de la barra de herramientas puede descartar el teclado, el código para esto es el siguiente:

En viewDidLoad

 toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; //toolbar is uitoolbar object toolBar.barStyle = UIBarStyleBlackOpaque; UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnClickedDone:)]; [toolBar setItems:[NSArray arrayWithObject:btnDone]]; 

En el método textviewdelegate

 - (BOOL)textViewShouldBeginEditing:(UITextView *)textView { [textView setInputAccessoryView:toolBar]; return YES; } 

En acción de Button Done que está en la barra de herramientas, está siguiendo:

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

La respuesta de josebama fue la respuesta más completa y limpia disponible en este hilo.

A continuación se muestra la syntax de Swift 3 :

 func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool { let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards) if text.characters.count == 1 && resultRange != nil { textView.resignFirstResponder() // Do any additional stuff here return false } return true } 

Al igual que el comentario mate a samvermette, tampoco me gusta la idea de detectar “\ n”. La tecla “devolver” está ahí por una razón en UITextView, que es ir a la siguiente línea de curso.

La mejor solución en mi opinión es imitar la aplicación de mensajes de iPhone, que es agregar una barra de herramientas (y un botón) en el teclado.

Recibí el código de la siguiente publicación del blog:

http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/

Pasos:

-Agregue la barra de herramientas a su archivo XIB – establezca la altura en 460

-Agregar elemento del botón de la barra de herramientas (si aún no se ha agregado). Si necesita alinear a la derecha, también agregue un elemento de botón de barra flexible a XIB, y mueva el elemento del botón de la barra de herramientas

-Crea acciones que vinculan el elemento del botón a resignFirstResponder de la siguiente manera:

 - (IBAction)hideKeyboard:(id)sender { [yourUITextView resignFirstResponder]; } 

-Entonces:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWillShow:(NSNotification *)notification { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; CGRect frame = self.keyboardToolbar.frame; frame.origin.y = self.view.frame.size.height - 260.0; self.keyboardToolbar.frame = frame; [UIView commitAnimations]; } - (void)keyboardWillHide:(NSNotification *)notification { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; CGRect frame = self.keyboardToolbar.frame; frame.origin.y = self.view.frame.size.height; self.keyboardToolbar.frame = frame; [UIView commitAnimations]; } 

Acabo de resolver este problema de otra manera.

  • Crea un botón que se colocará en el fondo
  • Desde el Inspector de atributos, cambie el tipo de botón a personalizado y el botón se vuelve transparente.
  • Expande el botón para cubrir toda la vista y asegúrate de que el botón esté detrás del rest del objeto. Una forma fácil de hacerlo es arrastrar el botón a la parte superior de la vista de lista en la vista
  • Controlar arrastre el botón al archivo viewController.h y cree una acción (Evento enviado: Touch Up Inside) como:

     (IBAction)ExitKeyboard:(id)sender; 
  • En ViewController.m debería verse así:

     (IBAction)ExitKeyboard:(id)sender { [self.view endEditing:TRUE]; } 
  • Ejecuta la aplicación, y cuando haces clic fuera de TextView, el teclado desaparece

Agregar un observador en viewDidLoad

 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil]; 

y luego usa el selector para verificar “\ n”

 -(void) textViewKeyPressed: (NSNotification*) notification { if ([[[notification object] text] hasSuffix:@"\n"]) { [[notification object] resignFirstResponder]; } } 

Utiliza “\ n” y no comprueba específicamente la clave de retorno, pero creo que está bien.

ACTUALIZAR

Consulte la respuesta de ribto a continuación, que usa [NSCharacterSet newlineCharacterSet] en lugar de \n

Usando el controlador de navegación para alojar una barra para cerrar el teclado:

en el archivo .h:

 UIBarButtonItem* dismissKeyboardButton; 

en el archivo .m:

 - (void)viewDidLoad { dismissKeyboardButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissKeyboard)]; } -(void)textViewDidBeginEditing:(UITextView *)textView { self.navigationItem.rightBarButtonItem = dismissKeyboardButton; } -(void)textFieldDidBeginEditing:(UITextField *)textField { self.navigationItem.rightBarButtonItem = dismissKeyboardButton; } -(void)dismissKeyboard { [self.textField resignFirstResponder]; [self.textView resignFirstResponder]; //or replace this with your regular right button self.navigationItem.rightBarButtonItem = nil; } 

Prueba esto :

  - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{ if ([text isEqualToString:@"\n"]) { [self.view endEditing:YES]; } return YES; } 

// Puedes usar esto …

Paso 1. El primer paso es asegurarse de declarar compatibilidad con el protocolo UITextViewDelegate . Esto se hace en su archivo de encabezado, como ejemplo aquí está el encabezado llamado

EditorController.h:

 @interface EditorController : UIViewController { UITextView *messageTextView; } @property (nonatomic, retain) UITextView *messageTextView; @end 

Paso 2. A continuación, deberá registrar el controlador como delegado de UITextView. Continuando con el ejemplo anterior, aquí es cómo he inicializado el UITextView con EditorController como el delegado …

 - (id) init { if (self = [super init]) { // define the area and location for the UITextView CGRect tfFrame = CGRectMake(10, 10, 300, 100); messageTextView = [[UITextView alloc] initWithFrame:tfFrame]; // make sure that it is editable messageTextView.editable = YES; // add the controller as the delegate messageTextView.delegate = self; } 

Paso 3. Y ahora la última pieza del rompecabezas es tomar medidas en respuesta al mensaje shouldCahngeTextInRange siguiente manera:

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { // Any new character added is passed in as the "text" parameter if ([text isEqualToString:@"\n"]) { // Be sure to test for equality using the "isEqualToString" message [textView resignFirstResponder]; // Return FALSE so that the final '\n' character doesn't get added return FALSE; } // For any other character return TRUE so that the text gets added to the view return TRUE; } 

rápido

 func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.resignFirstResponder() } return true } 

y configurar

código SWIFT

Implementa UITextViewDelegate en tu clase / vista así:

 class MyClass: UITextViewDelegate { ... 

establecer el delegado textView en uno mismo

 myTextView.delegate = self 

Y luego implemente lo siguiente:

  func textViewDidChange(_ textView: UITextView) { if textView.text.characters.count >= 1 { if let lastChar = textView.text.characters.last { if(lastChar == "\n"){ textView.text = textView.text.substring(to: textView.text.index(before: textView.text.endIndex)) textView.resignFirstResponder() } } } } 

EDITAR Actualicé el código porque nunca es una buena idea cambiar la entrada del usuario en un campo de texto para un workarround y no reiniciar el estado después de que se complete el código de hackeo.

También puede ocultar el teclado cuando toque en la pantalla de visualización:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch * touch = [touches anyObject]; if(touch.phase == UITouchPhaseBegan) { [txtDetail resignFirstResponder]; } } 

Swift respuesta:

 override func viewDidLoad() { super.viewDidLoad() let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:") view.addGestureRecognizer(tapGestureReconizer) } func tap(sender: UITapGestureRecognizer) { view.endEditing(true) } 

Usé este código para cambiar el respondedor.

  - (BOOL)textView:(UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text { if ([text isEqualToString:@"\n"]) { //[textView resignFirstResponder]; //return YES; NSInteger nextTag = textView.tag + 1; // Try to find next responder UIResponder* nextResponder = [self.view viewWithTag:nextTag]; if (nextResponder) { // Found next responder, so set it. [nextResponder becomeFirstResponder]; } else { // Not found, so remove keyboard. [textView resignFirstResponder]; } return NO; return NO; } return YES; } 

De acuerdo. Todo el mundo ha dado respuestas con trucos, pero creo que la forma correcta de lograrlo es mediante

Conectando la siguiente acción al evento ” Did End On Exit ” en el Interface Builder . (haga clic con el botón derecho en TextField y presione cntrl-drag desde ‘ Did end on exit ‘ hasta el siguiente método.

 -(IBAction)hideTheKeyboard:(id)sender { [self.view endEditing:TRUE]; } 
 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if (range.length==0) { if ([text isEqualToString:@"\n"]) { [txtView resignFirstResponder]; if(textView.returnKeyType== UIReturnKeyGo){ [self PreviewLatter]; return NO; } return NO; } } return YES; } 
 + (void)addDoneButtonToControl:(id)txtFieldOrTextView { if([txtFieldOrTextView isKindOfClass:[UITextField class]]) { txtFieldOrTextView = (UITextField *)txtFieldOrTextView; } else if([txtFieldOrTextView isKindOfClass:[UITextView class]]) { txtFieldOrTextView = (UITextView *)txtFieldOrTextView; } UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, [Global returnDeviceWidth], 50)]; numberToolbar.barStyle = UIBarStyleDefault; UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_return"] style:UIBarButtonItemStyleBordered target:txtFieldOrTextView action:@selector(resignFirstResponder)]; numberToolbar.items = [NSArray arrayWithObjects:btnDone,nil]; [numberToolbar sizeToFit]; if([txtFieldOrTextView isKindOfClass:[UITextField class]]) { ((UITextField *)txtFieldOrTextView).inputAccessoryView = numberToolbar; } else if([txtFieldOrTextView isKindOfClass:[UITextView class]]) { ((UITextView *)txtFieldOrTextView).inputAccessoryView = numberToolbar; } } 

La pregunta es cómo hacerlo con la tecla de retorno, pero creo que esto podría ayudar a alguien con la intención de hacer desaparecer el teclado al usar UITextView:

 @IBOutlet weak var textView: UITextView! private func addToolBarForTextView() { let textViewToolbar: UIToolbar = UIToolbar() textViewToolbar = UIBarStyle.Default textViewToolbar = [ UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.cancelInput)), UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil), UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.doneInput)) ] textViewToolbar() self.textView.inputAccessoryView = textViewToolbar //do it for every relevant textView if there are more than one } func doneInput() { self.textView.resignFirstResponder() } func cancelInput() { self.textView.text = "" self.textView.resignFirstResponder() } 

Llame a addToolBarForTextView () en viewDidLoad o en algún otro método del ciclo de vida.

Parece que fue la solución perfecta para mí.

Aclamaciones,

Murat

 -(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard) -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks 

Sé que no es la respuesta exacta a esta pregunta, pero encontré este hilo después de buscar en Internet una respuesta. Supongo que otros comparten ese sentimiento.

Esta es mi variante de UITapGestureRecognizer, que considero confiable y fácil de usar; basta con configurar el delegado de TextView en ViewController.

En lugar de ViewDidLoad agrego el UITAPGestureRecognizer cuando el TextView se activa para editarlo:

 -(void)textViewDidBeginEditing:(UITextView *)textView{ _tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)]; [self.view addGestureRecognizer: _tapRec]; NSLog(@"TextView Did begin"); } 

Cuando toco fuera de TextView, la vista finaliza el modo de edición y el UITAPGestureRecognizer se elimina para que pueda seguir interactuando con otros controles en la vista.

 -(void)tap:(UITapGestureRecognizer *)tapRec{ [[self view] endEditing: YES]; [self.view removeGestureRecognizer:tapRec]; NSLog(@"Tap recognized, tapRec getting removed"); } 

Espero que esto ayude. Parece tan obvio, pero nunca he visto esta solución en ninguna parte de la web. ¿Estoy haciendo algo mal?

No olvides configurar el delegado para textView; de lo contrario, resignfirstresponder no funcionará.

Prueba esto .

 NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]; 

Para Xcode 6.4., Swift 1.2. :

  override func touchesBegan(touches: Set, withEvent event: UIEvent) { super.touchesBegan(touches, withEvent: event) if let touch = touches.first as? UITouch { self.meaningTextview.resignFirstResponder() } } 

Mi hack para esto:

1- crea un botón que cubra toda la vista; 2- enviarlo al fondo de su vista, 3- cambiar su tipo de “Round Rect” a “Custom” en el Attribute Inspector, 4- crear una acción 5- implementar el método de acción:

 - (IBAction)bgTouched:(id)sender { //to dismiss keyboard on bg btn pressed [_userInput resignFirstResponder]; } 

donde _userInput es su salida de TextField