web-dev-qa-db-fra.com

Un moyen facile de rejeter le clavier?

De nombreux contrôles sont éparpillés dans de nombreuses cellules de mon tableau et je me demandais s’il existe un moyen plus simple d’écarter le clavier sans avoir à passer en revue tous mes contrôles et à les renvoyer en tant que premiers répondants. Je suppose que la question est .. Comment pourrais-je obtenir le premier répondeur actuel au clavier?

374
Seventoes

Essayer:

[self.view endEditing:YES];
791
kirby

Vous pouvez forcer la vue en cours d'édition à abandonner son statut de premier répondeur avec [view endEditing:YES]. Cela cache le clavier.

Contrairement à -[UIResponder resignFirstResponder], -[UIView endEditing:] recherchera dans les sous-vues pour trouver le premier répondant actuel. Ainsi, vous pouvez l'envoyer à votre vue de niveau supérieur (par exemple, self.view dans un UIViewController) et il agira comme il convient.

(Cette réponse incluait auparavant deux autres solutions, qui fonctionnaient également mais étaient plus compliquées que nécessaire. Je les ai supprimées pour éviter toute confusion.)

126
Nicholas Riley

Vous pouvez envoyer une action nulle à l'application, elle démissionnera à tout moment sans avoir à se soucier de la vue actuellement associée au statut de premier intervenant.

Objectif c:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

Swift 3.0:

UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)

Aucune action ciblée n'est commune à Mac OS X pour les commandes de menu, et voici une utilisation pour celles-ci sur iOS.

91
Travelling Man

Pour être honnête, je ne suis pas folle des solutions proposées ici. J'ai trouvé un bon moyen d'utiliser un TapGestureRecognizer qui, je pense, va au cœur de votre problème: lorsque vous cliquez sur un élément autre que le clavier, fermez le clavier.

  1. Dans viewDidLoad, inscrivez-vous pour recevoir les notifications du clavier et créez un UITapGestureRecognizer:

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    
    [nc addObserver:self selector:@selector(keyboardWillShow:) name:
    UIKeyboardWillShowNotification object:nil];
    
    [nc addObserver:self selector:@selector(keyboardWillHide:) name:
    UIKeyboardWillHideNotification object:nil];
    
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
    action:@selector(didTapAnywhere:)];
    
  2. Ajouter le clavier afficher/masquer les répondants. Là, vous ajoutez et supprimez le TapGestureRecognizer à UIView qui devrait fermer le clavier lorsque vous appuyez dessus. Remarque: Vous n'êtes pas obligé de l'ajouter à toutes les sous-vues ou contrôles.

    -(void) keyboardWillShow:(NSNotification *) note {
        [self.view addGestureRecognizer:tapRecognizer];
    }
    
    -(void) keyboardWillHide:(NSNotification *) note
    {
        [self.view removeGestureRecognizer:tapRecognizer];
    }
    
  3. TapGestureRecognizer appellera votre fonction quand elle obtiendra un appui et vous pourrez ignorer le clavier de la manière suivante:

    -(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer {    
        [textField resignFirstResponder];
    }
    

La bonne chose à propos de cette solution est qu’elle ne filtre que pour les taps, pas de balayage. Ainsi, si vous faites défiler le contenu au-dessus du clavier, les balayages continuent de défiler et de laisser le clavier affiché. En supprimant la reconnaissance des gestes après la disparition du clavier, les futures pressions sur votre vue sont traitées normalement.

56
Brett Levine

Ceci est une solution pour que le clavier disparaisse lorsque vous appuyez sur return dans tout champ de texte, en ajoutant du code à un endroit (il est donc inutile d'ajouter un gestionnaire pour chaque champ de texte):


considérez ce scénario:

j'ai un viewcontroller avec deux champs de texte (nom d'utilisateur et mot de passe). et le viewcontroller implémente le protocole UITextFieldDelegate

je fais cela dans viewDidLoad

- (void)viewDidLoad 
{
    [super viewDidLoad];

    username.delegate = self;
    password.delegate = self;
}

et le viewcontroller implémente la méthode optionnelle comme

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

et quel que soit le champ de texte dans lequel vous vous trouvez, dès que je tape return sur le clavier, il est renvoyé!

Dans votre cas, la même chose fonctionnerait tant que vous définissez tous les délégués du champ de texte sur self et que vous implémentiez textFieldShouldReturn

22
prakash

Une meilleure approche consiste à "voler" le statut de premier répondant.

UIApplication étant une sous-classe de UIResponder, vous pouvez essayer:

[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]

À défaut, créez un nouveau UITextField avec un cadre de taille zéro, ajoutez-le à une vue quelque part et procédez de la même manière (devenez suivi de démission).

Rangez-le dans une classe d’utilité.

+ (void)dismissKeyboard {
    [self globalResignFirstResponder];
}

+ (void) globalResignFirstResponder {
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    for (UIView * view in [window subviews]){
        [self globalResignFirstResponderRec:view];
    }
}

+ (void) globalResignFirstResponderRec:(UIView*) view {
    if ([view respondsToSelector:@selector(resignFirstResponder)]){
        [view resignFirstResponder];
    }
    for (UIView * subview in [view subviews]){
        [self globalResignFirstResponderRec:subview];
    }
}
7
lorean

@Nicholas Riley et @Kendall Helmstetter Geln & @cannyboy:

Absolument brillant!

Je vous remercie.

Compte tenu de vos conseils et de ceux des autres personnes dans ce fil, voici ce que j'ai fait:

À quoi ça ressemble quand utilisé:

[[self appDelegate] dismissKeyboard]; (note: j'ai ajouté appDelegate en tant qu'addition à NSObject pour que je puisse utiliser n'importe où sur n'importe quoi)

A quoi ça ressemble sous le capot:

- (void)dismissKeyboard 
{
    UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
    tempTextField.enabled = NO;
    [myRootViewController.view addSubview:tempTextField];
    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
}

EDIT

Amendement à ma réponse à inclus tempTextField.enabled = NO;. La désactivation du champ de texte empêchera l'envoi de notifications au clavier UIKeyboardWillShowNotification et UIKeyboardWillHideNotification si vous vous en remettiez dans l'ensemble de votre application.

6
Jeremy

Astuce pour savoir comment désactiver le clavier dans iOS lorsqu'un utilisateur touche n'importe où sur l'écran en dehors de UITextField ou du clavier. Compte tenu de l’immobilier que le clavier iOS peut occuper, il est logique d’offrir aux utilisateurs un moyen simple et intuitif d’écarter le clavier.

Voici n lien

5
Armen

Beaucoup de réponses trop compliquées ici, peut-être parce que ce n'est pas facile à trouver dans la documentation iOS. JosephH l'avait juste en haut:

[[view window] endEditing:YES];
5
Ian Wilkinson

Encore plus simple que la réponse de Meagar

écraser touchesBegan:withEvent:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [textField resignFirstResponder];`
}

Ceci va dismiss the keyboardsi vous touchez n'importe où dans le background.

4
user3032314

Voici ce que j'utilise dans mon code. Il fonctionne comme un charme!

Dans yourviewcontroller.h, ajoutez:

@property (nonatomic) UITapGestureRecognizer *tapRecognizer;

Maintenant, dans le fichier .m, ajoutez ceci à votre fonction ViewDidLoad:

- (void)viewDidLoad {
    //Keyboard stuff
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere:)];
    tapRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapRecognizer];
}

Ajoutez également cette fonction dans le fichier .m:

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

Dans Swift 3, vous pouvez effectuer les opérations suivantes:

UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
2
KeithC

Le meilleur moyen de supprimer le clavier de UITableView et UIScrollView est:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag
2
Manish Methani

Dans le fichier d’en-tête de votre contrôleur, ajoutez <UITextFieldDelegate> à la définition de l’interface de votre contrôleur afin qu’il soit conforme au protocole de délégué UITextField ...

@interface someViewController : UIViewController <UITextFieldDelegate>

... Dans le fichier d'implémentation du contrôleur (.m), ajoutez la méthode suivante ou le code qu'il contient si vous avez déjà une méthode viewDidLoad ...

- (void)viewDidLoad
{
    // Do any additional setup after loading the view, typically from a nib.
    self.yourTextBox.delegate = self;
}

... Ensuite, liez yourTextBox à votre champ de texte actuel

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
{
    if (theTextField == yourTextBox) {
        [theTextField resignFirstResponder];
    }
    return YES;
}
2
user1270998

Vous devez envoyer endEditing: à la fenêtre de travail en tant que sous-classe de UIView

[[UIApplication sharedApplication].windows.firstObject endEditing:NO];
2
malex

Et dans Swift on peut faire

UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)
1
Eike

Sous-classe vos champs de texte ... et aussi textviews

Dans la sous-classe, mettez ce code ..

-(void)conformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissKeyBoard) name:KEYBOARD_DISMISS object:nil];
}

-(void)deConformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] removeObserver:self name:KEYBOARD_DISMISS object:nil];
}

- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self resignFirstResponder];
}

Dans les champs de texte délégués (de la même manière pour les délégués TextView)

-(void)textFieldDidBeginEditing:(JCPTextField *)textField{
     [textField conformsToKeyboardDismissNotification];
}


- (void)textFieldDidEndEditing:(JCPTextField *)textField{
    [textField deConformsToKeyboardDismissNotification];
}

All set .. Maintenant, il suffit de poster la notification de n'importe où dans votre code. Il va démissionner n'importe quel clavier.

1
mmmanishs

Vous devrez peut-être également remplacer UIViewController DisablesAutomaticKeyboardDismissal pour que cela fonctionne dans certains cas. Cela peut être nécessaire sur le contrôleur UINavigation, si vous en avez un.

1
Craig Miller

Pour quitter un clavier après que le clavier est apparu, il y a 2 cas,

  1. quand UITextField est à l'intérieur d'une UIScrollView

  2. quand UITextField est en dehors d'une UIScrollView

2.lorsque UITextField se trouve en dehors d'un UIScrollView, remplacez la méthode dans votre sous-classe UIViewController

vous devez également ajouter un délégué pour tous UITextView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
}
  1. Dans une vue défilement, tapoter à l'extérieur ne déclenchera aucun événement, donc dans ce cas tilisez un outil de reconnaissance de gestes tactiles, faites glisser un élément ITapGesture pour la vue de défilement et créer un IBAction pour cela.

pour créer une action IBAction, appuyez sur ctrl + clic sur UITapGesture et faites-la glisser dans le fichier .h de viewcontroller.

Ici, j'ai nommé tappedEvent comme nom d'action.

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

les informations données ci-dessus ont été dérivées du lien suivant, s'il vous plaît se référer pour plus d'informations ou contactez-moi si vous ne comprenez pas les données ci-dessus.

http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/

1
user4993619

La réponse de Jeremy ne fonctionnait pas vraiment pour moi, je pense, car j'avais une pile de navigation dans une vue en onglet avec un dialogue modal par-dessus. J'utilise ce qui suit pour le moment et cela fonctionne pour moi, mais votre kilométrage peut varier.

 // dismiss keyboard (mostly macro)
[[UIApplication sharedApplication].delegate dismissKeyboard]; // call this in your to app dismiss the keybaord

// --- dismiss keyboard (in indexAppDelegate.h) (mostly macro)
- (void)dismissKeyboard;

// --- dismiss keyboard (in indexAppDelegate.m) (mostly macro)
// do this from anywhere to dismiss the keybard
- (void)dismissKeyboard {    // from: http://stackoverflow.com/questions/741185/easy-way-to-dismiss-keyboard

    UITextField *tempTextField = [[UITextField alloc] initWithFrame:CGRectZero];

    UIViewController *myRootViewController = <#viewController#>; // for simple apps (INPUT: viewController is whatever your root controller is called.  Probably is a way to determine this progragrammatically)
    UIViewController *uivc;
    if (myRootViewController.navigationController != nil) { // for when there is a nav stack
        uivc = myRootViewController.navigationController;
    } else {
        uivc = myRootViewController;
    }

    if (uivc.modalViewController != nil) { // for when there is something modal
        uivc = uivc.modalViewController;
    } 

    [uivc.view  addSubview:tempTextField];

    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
    [tempTextField release];

}
1
JJ Rohrer

la façon la plus simple est d'appeler la méthode

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    if(![txtfld resignFirstResponder])
    {
        [txtfld resignFirstResponder];
    }
    else
    {

    }
    [super touchesBegan:touches withEvent:event];
}
0
bharath gangupalli

Oui, endEditing est la meilleure option. Et à partir d'iOW 7.0, UIScrollView dispose d'une fonctionnalité intéressante pour ignorer le clavier lors de l'interaction avec la vue de défilement. Pour ce faire, vous pouvez définir la propriété keyboardDismissMode de UIScrollView.

Définissez le mode de fermeture du clavier comme suit:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag

Il a peu d'autres types. Jetez un coup d'oeil à ceci document Apple .

0
Shanmugaraja G

Une méthode légèrement plus robuste que je devais utiliser récemment:

- (void) dismissKeyboard {
    NSArray *windows = [UIApplication sharedApplication].windows;

    for(UIWindow *window in windows) [window endEditing:true];

    //  Or if you're only working with one UIWindow:

    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

J'ai trouvé que certaines des autres méthodes "globales" ne fonctionnaient pas (par exemple, UIWebView & WKWebView a refusé de démissionner).

0
mattsven

Dans Swift:

self.view.endEditing(true)
0
YannSteph

Ce n'est pas joli, mais la façon dont j'ai démissionné du premier répondeur quand je ne sais pas ce qu'est le répondeur:

Créez un UITextField, dans IB ou par programme. Faites le caché. Associez-le à votre code si vous l'avez créé dans IB. Ensuite, lorsque vous souhaitez ignorer le clavier, vous basculez le répondeur sur le champ de texte invisible et vous le résiliez immédiatement:

  [self.invisibleField becomeFirstResponder];
  [self.invisibleField resignFirstResponder];
0
cannyboy

Vous pouvez effectuer une itération récursive dans les sous-vues, stocker un tableau de tous les UITextFields, puis les parcourir en boucle et les renvoyer à tous.

Ce n'est pas vraiment une bonne solution, surtout si vous avez beaucoup de sous-vues, mais pour les applications simples, cela devrait faire l'affaire.

J'ai résolu ce problème de manière beaucoup plus compliquée, mais beaucoup plus performante, mais en utilisant un singleton/manager pour le moteur d'animation de mon application, et chaque fois qu'un champ de texte devenait le répondeur, je l'assignerais à un statique qui obtiendrait balayé sur la base de certains autres événements ... il est presque impossible pour moi d'expliquer dans un paragraphe.

Soyez créatif, cela ne m'a pris que 10 minutes pour réfléchir à cela pour mon application après avoir trouvé cette question.

0
M. Ryan

Mise à jour

J'ai trouvé un autre moyen simple

déclarez simplement une propriété: -

@property( strong , nonatomic) UITextfield *currentTextfield;

et une reconnaissance gestuelle du geste: -

@property (strong , nonatomic) UITapGestureRecognizer *resignTextField;

dans ViewDidLoad

_currentTextfield=[[UITextField alloc]init];
_resignTextField=[[UITapGestureRecognizer alloc]initWithTarget:@selector(tapMethod:)];

[self.view addGestureRecognizer:_resignTextField];

Implémente la méthode de délégué textfield didBeginEditing

 -(void)textFieldDidBeginEditing:(UITextField *)textField{


      _currentTextfield=textField;

    }

Implémentez votre méthode de geste Tap (_resignTextField)

 -(void)tapMethod:(UITapGestureRecognizer *)Gesture{

     [_currentTextfield resignFirstResponder];

 }
0
dreamBegin

Vous devez utiliser l'une de ces méthodes,

[self.view endEditing:YES];

ou

[self.textField resignFirstResponder];
0
Vaibhav Shiledar

Je déteste le fait qu’il n’existe aucun moyen "global" de supprimer par programmation le clavier sans utiliser les appels d’API privés. Fréquemment, j’ai besoin de fermer le clavier par programmation sans savoir quel objet est le premier intervenant. J'ai eu recours à l'inspection de self à l'aide de l'API d'exécution Objective-C, en énumérant toutes ses propriétés, en extrayant celles de type UITextField et en leur envoyant le message resignFirstResponder .

Ça ne devrait pas être si difficile de faire ça ...

0
CIFilter

Ajoutez un outil de reconnaissance des gestes tactiles à votre vue. Et définissez-le.

votre fichier .m sera comme

    - (IBAction)hideKeyboardGesture:(id)sender {
    NSArray *windows = [UIApplication sharedApplication].windows;
    for(UIWindow *window in windows) [window endEditing:true];
    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

Ça a fonctionné pour moi

0
Murat KAYA