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


382

En la biblioteca de IB, la introducción nos dice que cuando returnse presiona la tecla, el teclado UITextViewdesaparecerá. Pero en realidad la returnclave solo puede actuar como '\ n'.

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

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


Siga las instrucciones en esta publicación de blog: iphonedevelopertips.com/cocoa/…
ManojN

Respuestas:


354

UITextViewno tiene ningún método que se invocará cuando el usuario presione la tecla de retorno. Si desea que el usuario pueda agregar solo una línea de texto, use a UITextField. Al presionar la tecla de retorno y ocultar el teclado por un UITextViewno se siguen las pautas de la interfaz.

Aun así, si desea hacer esto, implemente el textView:shouldChangeTextInRange:replacementText:método UITextViewDelegatey, en esa verificación, si el texto de reemplazo es \n, oculte el teclado.

Puede haber otras formas, pero no conozco ninguna.


1
Gracias y el método funciona bien. La razón para usar UITextView es que puede contener texto en varias líneas. Y ahora lo estoy usando como un cuadro de mensaje.
Chilly Zhong el

28
Es bastante fácil de cambiar la tecla de retorno al "hecho" utilizando cualquiera [textField setReturnKeyType: UIReturnKeyDone];o usar constructor de interfaces
Casebash

99
Bien, ahora entiendo que la forma de Apple de terminar con un campo de texto de
varias líneas

8
Esta no es una buena manera de resolver esto porque está restringiendo al usuario a usar enter para salir del teclado. Probablemente la mejor manera es agregar un botón que ejecute el método resignFirstResponder.
Ele

55
@Casebash. Parece que establecer la tecla de retorno en "hecho" no resuelve el problema en Xcode 6.4, Swift 2.0. Configuré la clave usando IB.
MB_iOSDeveloper

505

Supuse que publicaría el fragmento aquí mismo:

Asegúrese de declarar soporte para el UITextViewDelegateprotocolo.

- (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
}

75
El problema es que esta no es realmente una forma de detectar que el usuario ha tocado la tecla de retorno . El usuario puede pegar un carácter de retorno en el campo de texto y obtendrá el mismo mensaje de delegado. Básicamente estás haciendo un mal uso de la vista de texto. La forma de descartar el teclado es (1) no hacerlo (como cuando redacta un mensaje en la aplicación de Correo) o (2) tener un botón Listo en otra parte de la interfaz (como en la aplicación de Notas). Puede adjuntar un botón como una vista de accesorios al teclado, por ejemplo.
mate

@ Sam V ese fragmento era un hombre genial. esto funciona para mi. muchas gracias hombre. ¿Hay algún fragmento para desechar el teclado numérico? saludos shishir
Shishir.bobby

Magnífico. Solo un recordatorio de que en algunas situaciones, para deshacerse del teclado, intente siguiendo las líneas ... [self.view endEditing: YES];
Fattie

@Vojto, funciona bien en iPad. Probablemente no haya configurado el delegado.
Vincent

44
El problema es que el teclado puede estar ocultando parte de la interfaz que se utiliza para descartar. Es realmente absurdo que IOS no tenga un botón en cada teclado dedicado a descartar el teclado para que el usuario pueda hacerlo si lo desea.
Sani Elfishawy

80

Sé que esto ya ha sido respondido, pero realmente no me gusta usar el literal de 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
}

66
Podría modificarlo así: NSRange resultRange = [text rangeOfCharacterFromSet: [NSCharacterSet newlineCharacterSet] opciones: NSBackwardsSearch]; Debido a que este es un truco de todos modos, parece que verificar el final de la cadena para un retorno podría ser una ruta más segura.
maxpower

@maxpower Muy buen comentario. Además, es mejor verificar el texto reemplazado, por ejemplo NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text].
Rudolf Adamkovič

Imagine a un usuario pegando un texto copiado de otro lugar que contiene una nueva línea. Probablemente se confundirían cuando, en lugar de agregar el texto, la aplicación simplemente cierre el teclado.
Nikolai Ruhe

44

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

Encontré las respuestas de samvermette y ribeto realmente útiles, y también el comentario de maxpower en la respuesta de ribeto . Pero hay un problema con esos enfoques. El problema que mate menciona en el samvermette 's respuesta y es que si el usuario quiere pegar algo con un salto de línea en su interior, el teclado ocultaría sin pegar nada.

Entonces, 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, por lo que nos aseguramos de que el usuario escriba en lugar de pegar.

Esto es lo que he hecho:

- (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;
}

Esta es una mejor solución para este problema. La respuesta de samvermette no tiene en cuenta la situación en la que el usuario desea pegar un texto.
marcopaivaf

36

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. Control-arrastre la vista al archivo de encabezado de ViewController y vincúlela como una acción con el evento como Retocar adentro, como:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

En el archivo principal de ViewController, ViewController.m:

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

Puede requerir un doble toque o toque prolongado utilizando técnicas similares. Es posible que deba configurar su ViewController para que sea UITextViewDelegate y conectar TextView al ViewController. Este método funciona tanto para UITextView como para UITextField.

Fuente: Big Nerd Ranch

EDITAR: También me gustaría agregar que si está utilizando un UIScrollView, la técnica anterior puede no funcionar tan fácilmente a través del Creador de interfaces. En ese caso, puede 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á.


1
Me gusta la idea, GestureRecognizerpero el gran problema es que ya no se puede hacer clic en todos los botones o controles de la vista.
experto

35

Agregue este método en su controlador de vista.

Rápido :

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()
        }
    }
}

2
No olvides confirmar el protocolo UITextViewDelegate :)
swiftBoy

No creo que sea una buena idea anular los toques de inicio y no llamar super.touchesBegan(touches:withEvent:).
TGO

Para expresar la naturaleza simétrica de este código, debe escribir else { return true }.
significado-asuntos

@ el significado no importa en absoluto
Alexander Volkov

@AlexanderVolkov No está de acuerdo con que sea una situación simétrica, no sabe a qué me refiero, ¿no cree en el valor del código semánticamente correcto o ...?
significado importa el

26
-(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 olvides confirmar el protocolo

SI no agregaste if([text isEqualToString:@"\n"])no puedes editar


2
-1 Esta es solo una versión más pobre de la respuesta de samvermette. Te perdiste regresar NOsi el texto es igual a @"\n".
devios1

17

Hay otra solución mientras se usa con uitextview, puede agregar la barra de herramientas como InputAccessoryView en "textViewShouldBeginEditing", y desde el botón Listo de esta barra de herramientas puede descartar el teclado, el código para esto es el siguiente:

En vistaDidLoad

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];
}

17

Encontré la respuesta de josebama era la respuesta más completa y limpia disponible en este hilo.

A continuación se muestra la sintaxis de Swift 4 :

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

El resultRangeobjetivo es probar si el texto solo contiene nuevas líneas que evitan el código "\ n".
Qinghua

6

rápido

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

y configurar


¿De dónde es esa captura de pantalla?
Sam

6

Uso del controlador de navegación para alojar una barra para descartar 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;
}

5

Al igual que Matt comenta a Samvermette, tampoco me gusta la idea de detectar "\ n". La tecla "volver" está ahí por una razón en UITextView, que es ir a la siguiente línea, por supuesto.

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.

Obtuve el código de la siguiente publicación de 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 de botón de barra de herramientas (si aún no se ha agregado). Si necesita alinearlo a la derecha, agregue también un elemento de botón de barra flexible a XIB y mueva el elemento de botón de barra de herramientas

-Cree acciones que vinculen el elemento de su botón para renunciar FirstResponder 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];
}

Sin relación. Si bien su solución es elegante, no responde a la pregunta original: "¿Cómo descartar el teclado para UITextView con la tecla de retorno?". Hay situaciones en las que se utiliza UITextView para simular una palabra envolviendo UITextField, no para ingresar varias líneas.
SwiftArchitect

2
Aunque está fuera de tema, es muy útil. También quiero que se ingrese un UITextView con varias líneas y descarte el teclado cuando lo desee.
Yeung

5

Acabo de resolver este problema de una manera diferente.

  • Crea un botón que se colocará en segundo plano
  • Desde el Inspector de atributos, cambie el tipo de botón a personalizado, y esto hace que el botón sea transparente.
  • Expanda el botón para cubrir toda la vista y asegúrese de que el botón esté detrás de todos los demás objetos. Una manera fácil de hacer esto es arrastrar el botón a la parte superior de la vista de lista en la Vista
  • Control arrastre el botón al viewController.harchivo y cree una acción (Evento enviado: Retocar adentro) como:

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

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

También debe agregar: - (nulo) textViewDidEndEditing: (UITextView *) textView {[self.TextView resignFirstResponder]; }
samouray

5

Agregar un observador en viewDidLoad

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

y luego use el selector para verificar "\ n"

-(void) textViewKeyPressed: (NSNotification*) notification {

  if ([[[notification object] text] hasSuffix:@"\n"])
  {
    [[notification object] resignFirstResponder];
  }
}

Utiliza "\ n" y no busca específicamente una clave de retorno, pero creo que esto está bien.

ACTUALIZAR

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


Err utiliza \ny la clave de retorno se detecta en función de \nlo que comprueba la clave de retorno. La única diferencia es que está utilizando notificaciones en lugar de utilizar textViewDelegates.
GoodSp33d

Ahora creo que buscar en [NSCharacterSet newlineCharacterSet]lugar de \ n podría ser una mejor manera de hacerlo.
ToddB

5

código SWIFT

Implemente UITextViewDelegate en su clase / Vista así:

class MyClass: UITextViewDelegate  { ...

establecer el delegado textView en self

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 He actualizado el código porque nunca es una buena idea cambiar la entrada del usuario en un campo de texto para un entorno de trabajo y no restablecer el estado después de que se complete el código de pirateo.


4

Prueba esto :

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

    return YES;

}

4

// Puedes usar esto ...

Paso 1. El primer paso es asegurarte de que declaras soporte para el UITextViewDelegateprotocolo. Esto se hace en su archivo de encabezado, como ejemplo aquí es 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, así es como he inicializado UITextViewcon EditorControllercomo 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 pieza final del rompecabezas es actuar en respuesta al shouldCahngeTextInRangemensaje de la 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;
}

3

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

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

En mi humilde opinión, este es un enfoque muy bueno, mucho mejor que con el botón que cubre toda la vista.
WebOrCode

3

Respuesta rápida:

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

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}

3

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;

    }

por qué no usar [self.view endEditing: YES]; ¿¿una vez??
ajay_nasa

3

La pregunta pregunta 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:

private func addToolBarForTextView() {
    let textViewToolbar: UIToolbar = UIToolbar()
    textViewToolbar.barStyle = .default
    textViewToolbar.items = [
        UIBarButtonItem(title: "Cancel", style: .done,
                  target: self, action: #selector(cancelInput)),
        UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
                  target: self, action: nil),
        UIBarButtonItem(title: "Post Reply", style: .done,
                  target: self, action: #selector(doneInput))
    ]
    textViewToolbar.sizeToFit()
    yourTextView.inputAccessoryView = textViewToolbar
}

@objc func cancelInput() { print("cancel") }
@objc func doneInput() { print("done") }

override func viewDidLoad() {
    super.viewDidLoad()
    addToolBarForTextView()
}

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

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

Salud,

Murat


1
Para 2019 ahora copie y pegue, sin errores de sintaxis y nombres actuales
Fattie

1
Con mucho, la mejor respuesta aquí. Acabo de corregir el simple error de sintaxis, por supuesto edite como desee. ¡Gracias!
Fattie

2

Okay. Todos han dado respuestas con trucos, pero creo que la forma correcta de lograr esto es mediante

Conectando la siguiente acción al evento " Terminó al salir " en Interface Builder. (haga clic con el botón derecho TextFieldy arrastre cntrl desde 'Finalizó al salir ' al siguiente método.

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

66
-1 La pregunta es sobre UITextView y no UITextField, mi amigo
Yogi

2
La mayoría de estas respuestas están aquí con votos porque se adapta a varios escenarios de diferentes desarrolladores.
carbonr el

Si está utilizando un UITextField, esta es la forma de hacerlo. Por cierto, debe usar SÍ / NO para las BOOL de Objective-C, no VERDADERO / FALSO.
Jon Shier

1
@jshier: VERDADERO / FALSO también está bien
Yogi

2

Simular a otras respuestas usando la UITextViewDelegateinterfaz rápida pero más nueva isNewlinesería:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}

1
- (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;
}

1
+ (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;
    }
}

0

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

Esta es mi variación del UITapGestureRecognizer que encuentro confiable y fácil de usar: solo configure el delegado de TextView en ViewController.

En lugar de ViewDidLoad, agrego UITapGestureRecognizer cuando TextView se activa para editar:

-(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 UITapGestureRecognizer se elimina para poder continuar 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?


0

No olvide configurar el delegado para textView; de lo contrario, renunciar a la primera respuesta no funcionará.


0

Prueba esto .

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

0

Para Xcode 6.4., Swift 1.2. :

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

0

Debería agregar UIToolbara UITextView superior para facilitar en lugar de usarshouldChangeTextIn

En Swift 4

let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        toolbar.barStyle = .default
        toolbar.items = [
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneAction))
        ]
        textView.inputAccessoryView = toolbar
@objc func doneAction(){
 self.textView.resignFirstResponder()
}

Con mucho, la mejor solución. Tenga en cuenta que en lugar de configurar el marco, simplemente usetoolbar.sizeToFit()
Fattie
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.