Descartar el teclado tocando el fondo de UITableView


105

Tengo una UITableViewcon UITextFields como celdas. Me gustaría descartar el teclado cuando UITableViewse toca el fondo del . Estoy tratando de hacer esto creando un UIButtontamaño del UITableViewy colocándolo detrás del UITableView. El único problema es UIButtoncaptar todos los toques incluso cuando el toque está en UITableView. ¿Qué estoy haciendo mal?

¡Gracias!


Preguntas y respuestas repetidas: Q1 , Q2 , Q3 .
Yantao Xie

Esta es la mejor respuesta stackoverflow.com/a/12851794/1418457
onmyway133

Respuestas:


203

Esto se hace fácilmente creando un objeto UITapGestureRecognizer (de forma predeterminada, esto detectará un "gesto" en un solo toque, por lo que no se requiere más personalización), especificando un objetivo / acción para cuando se dispara el gesto y luego adjuntando el objeto reconocedor de gestos a la vista de su mesa.

Por ejemplo, quizás en su viewDidLoadmétodo:

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];

Y el hideKeyboardmétodo podría verse así:

- (void) hideKeyboard {
    [textField1 resignFirstResponder];
    [textField2 resignFirstResponder];
    ...
    ...
}

Tenga en cuenta que el gesto no se dispara al tocar el interior de un UITextFieldobjeto. Se dispara en el UITableViewfondo, la vista de pie de página, la vista de encabezado y en UILabelsceldas internas, etc.


4
Cuando probé esto, descubrí que impedía que la tabla seleccionara celdas :(. Solución impresionante de lo contrario
Brian

109
Como una solución a continuación señala, puede hacer que esto funcione mucho mejor configurando:gestureRecognizer.cancelsTouchesInView = NO;
Zebs

3
Y no te olvides de liberar el gestoRecognizer una vez que esté adjunto a tableView.
Paul Lynch

39
Para el hideKeyboardmétodo, en lugar de comunicarse directamente con los campos de texto, puede hacerlo [self.view endEditing:NO];. De los documentos de Apple: " Este método examina la vista actual y su jerarquía de subvista para el campo de texto que es actualmente el primer respondedor. Si encuentra uno, le pide al campo de texto que renuncie como primer respondedor. Si el parámetro de fuerza está configurado en SÍ, el campo de texto ni siquiera se pregunta; se ve obligado a renunciar "
Gobot

1
de esta manera, mi método "didSelectRowAtIndexPath" no se llama. alguna solución para esto ??
uniruddh

127

La solución UITapGestureRecognizer funciona con la selección de celdas de la tabla si establece:

gestureRecognizer.cancelsTouchesInView = NO;

1
Esto permite tocar la celda, pero el gesto también se reconoce, tal vez deberíamos implementar estos métodos de delegadoshouldReceiveTouch
onmyway133

61

Esta es la mejor forma de hacerlo. Solo haz esto

[self.view endEditing:YES];

o

[[self.tableView superView] endEditing:YES];

¿Dónde debo poner este código? lo siento soy principiante. Y proporcione un código rápido.
John

54

También puedes hacerlo desde Storyboard: ingrese la descripción de la imagen aquí


1
Lo que elija: Descartar al arrastrar, Descartar interactivamente, cuando toco la celda de la tabla, se selecciona. Estoy usando Xcode 8, swift 3. por favor ayuda
John

22

Como UITableViewes una subclase de UIScrollView, implementar un método de delegado a continuación proporciona una solución rápida y extremadamente fácil. No hay necesidad de involucrarse, resignFirstResponderya que la jerarquía de vista hace introspecciones y encuentra al respondedor actual y le pide que renuncie a su estado de respondedor.

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

Y recuerde agregar UIScrollViewDelegateal archivo de encabezado.


2
Esto se puede hacer a través de este delineador como lo señaló @Joe Masilotti si está apuntando a iOS7 y superior: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri

¿Qué sucede si toca un campo de texto en la parte inferior de la pantalla que se supone que se desplaza hacia arriba para mostrar el teclado? - Tu teclado estará oculto.
Islam Q.14 de

Swift 4 - self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag
RobLabs

13

En primer lugar, escuche scrollViewWillBeginDraggingsu UIViewControlleragregando elUIScrollViewDelegate :

En archivo .h:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

En archivo .m:

- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {

    [self dismissKeyboard];

}

Luego escuche otras interacciones:

- (void)setupKeyboardDismissTaps {

    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeDownGestureRecognizer.cancelsTouchesInView = NO;
    swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
    [self.tableView addGestureRecognizer:swipeDownGestureRecognizer];

    UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];

    UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeRightGestureRecognizer.cancelsTouchesInView = NO;
    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:swipeRightGestureRecognizer];


    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Luego implemente dismissKeyboard:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

Y si, como yo, quisiera descartar el teclado para un UITextField dentro de una celda de tabla personalizada:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [customCell.textFieldInCell resignFirstResponder]; 

}

¡Espero que ayude a cualquiera que busque!



8

Aquí está la versión rápida para su placer de codificación:

Agrega un reconocedor de gestos de toque y luego cierra el teclado. ¡No se requiere salida para TextField!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .Ended {
        view.endEditing(true)
    }
    sender.cancelsTouchesInView = false
}

1
¡Esto funciona incluso con un tableViewCell personalizado! He pasado mucho tiempo tratando de resolver esto. Muchas gracias! Eres mi héroe. youtu.be/EqWRaAF6_WY
peacetype

8

Existe la versión Swift 3 sin bloquear los toques en las celdas.

En viewDidLoad()método:

let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)

Y se hideKeyboardve así:

func hideKeyboard() {
    view.endEditing(true)
}

7

Lo hice así:

Cree un método en su TableViewController para desactivar el primer respondedor (que sería su TextBox en ese momento)

- (BOOL)findAndResignFirstResonder:(UIView *)stView {
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }

    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder:subView]) {
            return YES;
        }
    }
    return NO;
}

En tableView:didSelectRowAtIndexPath:llamar al método anterior:

- (void)tableView:(UITableView *)tableView
                             didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    [self findAndResignFirstResonder: self.view];
    ...
}

lo está haciendo mal de la manera que lo pide. no pone un botón en la vista le dice a la vista que elimine el teclado como dice esta respuesta

2
Esto funciona maravillosamente si toca dentro de una celda de vista de tabla (y fuera de cualquier UITextField dentro de esa celda de vista de tabla). Sin embargo, si toco el fondo de la vista de tabla (que a menudo es un objetivo más fácil de alcanzar, ¡sí, ley de Fitts!), No tengo tanta suerte. Es cierto, eso es lo esperado, ya que estamos realizando esta operación dentro de tableView: didSelectRowAtIndexPath :. Si esto se puede ajustar de alguna manera para que funcione tocando en cualquier otro lugar de la vista de tabla (que de otro modo no querría el enfoque del teclado), ¡creo que tenemos un ganador aquí!
Joe D'Andrea

Tengo el mismo problema que jdandrea. Eso didSelectRowAtIndexPathno se dispara si toca el TableView en sí.
zekel

Si didSelectRowAtIndexPath no es suficiente, ¡haga lo mismo en touchesBegan también!
Amogh Talpallikar

5

Tuve una UITableViewControllery la implementación touchesBegan:withEvent:no funcionó para mí.

Esto es lo que funcionó:

Rápido:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    view.endEditing(true)
}

C objetivo:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}

Buena idea, me gusta.
HotFudgeSunday

4
@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

Luego asegúrese de que en su archivo Nib establezca el tipo de su UITableView en DismissableUITableView ..... tal vez podría haber pensado en un mejor nombre para esta clase, pero entiende el punto.


4

Si tiene como objetivo iOS7, puede usar uno de los siguientes:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

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

Tenga en cuenta que estos son de UIScrollView, que UITableViewhereda de.


bonito. Me las arreglé para romperlo deslizando el dedo hacia abajo desde lo alto de la pantalla hasta que el teclado comenzó a moverse hacia abajo, luego volví a deslizarlo hacia arriba hasta que el teclado se movió un poco hacia arriba y luego lo solté. la vista de desplazamiento no vuelve a la parte superior como debería.
Sam

3

Prueba esto:

viewDidLoad(){

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))

    tableView.addGestureRecognizer(tap)

}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {

    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

}

2

UITableView es una subclase de UIScrollView.

La forma en que lo hice fue escuchar un evento de desplazamiento por parte del usuario y luego resignFirstResponder. Aquí está el método UIScrollViewDelegate para implementar en su código;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

Al abordar este tipo de problemas, he encontrado que la mejor manera es investigar los protocolos delegados para cada objeto y los de las clases principales (en este caso, UITableViewDelegate, UIScrollViewDelegate. El número de eventos que dispara los objetos NS es bastante grande y completo. también es más fácil implementar un protocolo que subclasificar cualquier cosa.


2

Tuve el mismo problema y aquí está mi solución, funciona perfectamente para mí:

En la vista o el controlador de vista que implementó <UITextFieldDelegate>

(En mi caso tengo una costumbre UITableViewCell llamado TextFieldCell),

Declare el UITapGestureRecognizercomo una propiedad:

@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
    UITextField *theTextField;
    UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer; 

E inicialícelo en su vista / controlador:

self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];

En el - (void)textFieldDidBeginEditing:(UITextField *)textFieldmétodo, use superViewpara moverse hasta su tableView y llame addGestureRecognizer:

[self.superview.superview addGestureRecognizer:gestureRecognizer];

Y en el - (void)textFieldDidEndEditing:(UITextField *)textField, simplemente elimine el reconocedor de gestos:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

Espero eso ayude.


Esto lo hizo por mí. Gracias hac.jack
gilsaints88

2

Quería que mi celda abriera el teclado cuando se seleccionara cualquier parte de la celda y que la cerrara si hacía clic en cualquier parte fuera de la celda. Para abrir el teclado:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (selected)
    {
        [self.textField becomeFirstResponder];
    }
}

(NOTA: he subclasificado la celda, pero puede lograrlo fácilmente en el tableView:didSelectRowAtIndexPath:método delegado deUITableView )

Hacer esto significaba que con las soluciones principales, si hacía clic en la celda dos veces, el teclado temblaría, ya que, primero, el reconocedor de gestos intentó cerrar el teclado y, en segundo lugar, la celda se volvió a seleccionar e intentó abrir el teclado.

La solución es verificar si el clic ocurrió dentro de la celda seleccionada actualmente:

- (void)viewDidLoad
{
    [super viewDidLoad];
    //gesture recognizer to close the keyboard when user taps away
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard:)];
    tap.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tap];
}

-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
    if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
    {
        [self.view endEditing:YES];
    }
}

2

Encontré una solución que funciona muy bien.

Se necesita para usar UIGestureRecognizerDelegate y el método - gestoRecognizer: shouldReceiveTouch: .

Agregue el reconocedor de gestos a TableView de la siguiente manera:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

Luego, implemente el método delegado shouldReceiveTouch para rechazar los toques que se realizan en la clase UITableViewCell. El método hideKeyboard solo se llamará cuando el toque se haya realizado fuera de la clase UITableViewCell.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES; // handle the touch
}

- (void) hideKeyboard{
    [textField resignFirstResponder];
}

2

UITableViewtiene una backgroundViewpropiedad útil , con la que logré este comportamiento sin interferir con la selección de celda, como se muestra a continuación en Swift:

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)


1

Simplemente usando un UITapGestureRecognizer y cancelsTouchesInView = NOsignifica que los toques en las celdas y UITextViews también activan la ocultación. Esto es malo si tiene múltiples UITextViews y toca el siguiente. El teclado comenzará a ocultarse y luego el siguiente textView se convierte en el primer Respondedor y el teclado se vuelve visible nuevamente. Para evitar esto, verifique la ubicación del grifo y solo oculte el teclado si el grifo no está en una celda:

// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];


// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:tap.view];
    [self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}

Para scrollViewWillBeginDragging:que se active, la scrollEnabledpropiedad tableView debe serYES

// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

Perfecto para mi. Se agregó un cuadro de texto a la celda de vista de tabla; si toco fuera del teclado descartar
Nicola

0

¿Por qué quieres crear una tabla llena de campos de texto? Debería utilizar una vista detallada para cada fila que contiene los campos de texto. Cuando presione su vista detallada, asegúrese de llamar a "[myTextField BecomeFirstResponder]" para que el usuario pueda comenzar a editar con solo un clic de distancia de la lista de la tabla.


La aplicación Contactos de Apple hace precisamente esto. No diría que está lleno de campos de texto per se, pero los usa con buenos resultados.
Joe D'Andrea

2
Editar texto en línea en una vista de tabla es mucho más rápido e intuitivo que presionar vistas de detalles para cada campo de texto que el usuario desea editar ... solo pregunte a su formulario HTML más cercano, o los campos de texto en los paneles de Preferencias de iPhone, o la aplicación Contactos, o etc etc etc ... es una verdadera lástima que Apple no haya hecho de este un tipo de celda estándar, pero hay mucha información en la web sobre cómo lograrlo.
Glenc

0

Si está dispuesto a subclasificar (¡uf!) La vista de su tabla, algo como esto podría funcionar:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}

0

Si desea cerrar el teclado mientras se presiona la tecla de retorno, simplemente puede agregar el siguiente código en el método de retorno de textField, es decir:

- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
   [textField resignFirstresponder];
}

Algunos campos de texto pueden tener una vista de selector o alguna otra como subvista, por lo que en ese caso el método anterior no funciona, por lo que en ese caso debemos hacer uso de la clase UITapGestureRecognizer, es decir, agregar el siguiente fragmento de código al método viewDidLoad, es decir:

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

    [self.view addGestureRecognizer:tap];

Ahora simplemente agregue el respondedor de renuncia al método selector, es decir:

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

Espero que ayude, gracias :)


0

Muchas respuestas interesantes. Me gustaría compilar diferentes enfoques en la solución que pensé que se ajusta mejor a un escenario de UITableView (es el que suelo usar): lo que normalmente queremos es básicamente ocultar el teclado en dos escenarios: al tocar fuera de los elementos de la interfaz de usuario de texto, o al desplazarse hacia abajo o hacia arriba en UITableView. El primer escenario lo podemos agregar fácilmente a través de TapGestureRecognizer, y el segundo a través del método UIScrollViewDelegate scrollViewWillBeginDragging :. Primera orden del día, el método para ocultar el teclado:

   /**
     *  Shortcut for resigning all responders and pull-back the keyboard
     */
    -(void)hideKeyboard
    {
        //this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
        [self.tableView endEditing:YES];

    }

Este método renuncia a cualquier interfaz de usuario de textField de las subvistas dentro de la jerarquía de vista UITableView, por lo que es más práctico que renunciar a cada elemento de forma independiente.

A continuación, nos encargamos de descartar mediante un gesto Tap externo, con:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setupKeyboardDismissGestures];

}

- (void)setupKeyboardDismissGestures
{

//    Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
//    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
//    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
//    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
    //this prevents the gestureRecognizer to override other Taps, such as Cell Selection
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Establecer tapGestureRecognizer.cancelsTouchesInView en NO es para evitar que el gestoRecognizer anule el funcionamiento interno normal de UITableView (por ejemplo, para no interferir con la selección de celda).

Finalmente, para manejar ocultar el teclado al desplazarse hacia arriba / abajo en UITableView, debemos implementar el método scrollViewWillBeginDragging: del protocolo UIScrollViewDelegate, como:

archivo .h

@interface MyViewController : UIViewController <UIScrollViewDelegate>

archivo .m

#pragma mark - UIScrollViewDelegate

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self hideKeyboard];
}

¡Espero que ayude! =)


0

Así es como finalmente hice las obras. Combiné sugerencias y códigos de diferentes respuestas. Funciones: descartar el teclado, mover los campos de texto sobre el teclado mientras se edita y se configura el tipo de retorno del teclado "Siguiente" y "Listo". REEMPLAZAR "..." con más campos

static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;

@interface ViewController () <UITextFieldDelegate>
 @property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
  .....// some other text fields
 @property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end

@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(tapScreen:)];// outside textfields

[self.view addGestureRecognizer:tapGesture];

// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];

// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];

// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self     selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self      selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
  if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
  ...
  if([self.emailTXT isFirstResponder])[self.emailTXT  resignFirstResponder];

  }
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   if(textField.returnKeyType==UIReturnKeyNext) {
     // find the text field with next tag
     UIView *next = [[textField superview] viewWithTag:textField.tag+1];
     [next becomeFirstResponder];
   } else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
    [textField resignFirstResponder];
 }
return YES;
}

// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
   CGRect viewFrame = self.view.frame;
   CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
   CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
   CGFloat textFieldBottomLine = textFieldRect.origin.y + textFieldRect.size.height + LITTLE_SPACE;//

   CGFloat keyboardHeight = keyboardSize.height;

   BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
  if (isTextFieldHidden) {
    animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
    viewFrame.origin.y -= animatedDistance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
  return YES;
}

-(void) restoreViewFrameOrigionYToZero{
  CGRect viewFrame = self.view.frame;
  if (viewFrame.origin.y != 0) {
    viewFrame.origin.y = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
}

-(void)keyboardDidShow:(NSNotification*)aNotification{
   NSDictionary* info = [aNotification userInfo];
   keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
 }

-(void)keyboardDidHide:(NSNotification*)aNotification{
   [self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its  zero origin
}
@end

0

La respuesta de @ mixca es muy útil, pero ¿y si tengo algo diferente de UITextField? Creo que la mejor manera de manejarlo es buscar todas las subvistas de la vista principal con función recursiva, ver el ejemplo a continuación

- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
    [self resignFirstResponder];
    return YES;
}

    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResponder]) {
            return YES;
        }
    }
    return NO;
}

y también puede poner este método en su clase de utilidad y puede usarlo desde el gesto de toque como la respuesta de @ mixca.


0

Rápido 4 / 4.2 / 5

También puede cerrar el teclado cuando se toca una celda, antes de hacer cualquier otra cosa.

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    view.endEditing(true)
    // Do something here
    }

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.