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?
Essayer:
[self.view endEditing:YES];
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.)
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.
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.
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:)];
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];
}
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.
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
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];
}
}
@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.
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
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];
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 keyboard
si vous touchez n'importe où dans le background
.
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];
}
Dans Swift 3, vous pouvez effectuer les opérations suivantes:
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
Le meilleur moyen de supprimer le clavier de UITableView et UIScrollView est:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag
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;
}
Vous devez envoyer endEditing:
à la fenêtre de travail en tant que sous-classe de UIView
[[UIApplication sharedApplication].windows.firstObject endEditing:NO];
Et dans Swift on peut faire
UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)
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.
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.
Pour quitter un clavier après que le clavier est apparu, il y a 2 cas,
quand UITextField est à l'intérieur d'une UIScrollView
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];
}
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/
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];
}
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];
}
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 .
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).
Dans Swift:
self.view.endEditing(true)
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];
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.
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];
}
Vous devez utiliser l'une de ces méthodes,
[self.view endEditing:YES];
ou
[self.textField resignFirstResponder];
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 ...
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