web-dev-qa-db-fra.com

Comment annuler le premier répondant du champ de texte lorsque l'utilisateur appuie ailleurs?

J'ai rempli ma vue avec ScrollView (même taille que la vue) et je ne sais pas comment renoncer au premier répondant lorsque l'utilisateur appuie ailleurs dans la vue (ou dans la vue à défilement). Une idée sur comment faire ça? J'utilise la méthode suivante mais cela ne fonctionne pas comme prévu:

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

Merci d'avoir aidé,

Stéphane

24
Steve

J'ai trouvé une réponse ici: link

Si votre but ultime est simplement de démissionner du premier répondant, ceci devrait fonctionner: [self.view endEditing: YES]

Cette méthode est conçue pour cela! Référence: endEditing:

Force la vue (ou l'un de ses champs de texte incorporés) à renoncer au statut de premier répondeur.

79
DanSkeel

Pour une solution plus robuste et plus propre, ajoutez un outil de reconnaissance des gestes tactiles à votre vue principale. 

Cela fonctionnera mieux avec les vues imbriquées et sera plus propre que les boutons secrets du générateur de code et d'interface utilisateur.

A votre avis, avez-vous chargé:

UITapGestureRecognizer* tapBackground = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard:)];
[tapBackground setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:tapBackground];

..et définissez votre action cible à déclencher:

-(void) dismissKeyboard:(id)sender
{
    [self.view endEditing:YES];
}
18
Andres Canella

La meilleure option est le plus court chemin;)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
9
Onder OZCAN

Pour Swift 3 et Swift 4 vous pouvez le faire:

func viewDidLoad() {
    super.viewDidLoad()

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

    self.view.addGestureRecognizer(tap)
}

@objc func hideKeyboardByTappingOutside() {
    self.view.endEditing(true)
}
8
pableiros

UIViewController hérite de UIResponder donc une manière naïve (je suis à peu près sûr que ce n'est pas la façon la plus intelligente de le faire) serait d'écraser les méthodes suivantes (au moins une d'entre elles)

– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
- touchesCancelled:withEvent:

Ensuite, vous pouvez obtenir la vue touchée en faisant

UITouch *touch = [touches anyObject];
UIView *touchedView = [touch view];

enfin, renoncez au premier répondant si cette vue n'est pas votre champ de texte

if(touchedView != textField){
    [textField resignFirstResponder];
}

_

Démérites de cette approche:

Vous devrez gérer le "robinet" par vous-même. (Même problème que l'ancien iOS 3.1 ou antérieur). Vous devrez créer votre propre implémentation pour différencier les robinets simples des traînées, des balayages, des tapotements doubles, des tapotements longs, etc. Il n’est pas difficile de le faire fonctionner correctement, mais il est peu probable que vous l’obteniez de la même manière que Apple détecte les taps (timings, distances, seuils comptent!) Cependant, cela dépend de vos besoins.

Si votre structure de vues est assez simple, vous pouvez ajouter un identificateur de mouvements à la vue Conteneur et démissionner du premier intervenant chaque fois que le gestionnaire est appelé :)

J'espère que cela t'aides

4
nacho4d

Personne n'a encore présenté la meilleure réponse ici:

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

De la documentation sur cette méthode:

Normalement, cette méthode est appelée par un objet UIControl que l'utilisateur a touché. L'implémentation par défaut distribue la méthode d'action à l'objet cible donné ou, si aucune cible n'est spécifiée, au premier répondeur . Les sous-classes peuvent remplacer cette méthode pour effectuer des opérations spéciales envoi de messages d'action.

J'ai mis en gras la partie pertinente de ce paragraphe. En spécifiant nil pour le paramètre to:, nous appelons automatiquement le sélecteur donné sur le premier répondeur, où qu'il se trouve, et nous n'avons pas besoin de savoir où il se trouve dans la hiérarchie des vues. Cela peut également être utilisé pour invoquer d'autres méthodes sur le premier intervenant, pas seulement pour le faire renoncer à son statut.

3
Gavin
    -(BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self.TextField resignFirstResponder];

    return YES;
}
3

Donnez une étiquette unique à votre UITextfield (c'est-à-dire 333), puis, pour démissionner du premier répondant, procédez comme suit:

UITextField *textField = (UITextField *)[self.view viewWithTag:333];
[textField resignFirstResponder];
2
Lefteris
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(TapTodissmiss)];

[self.view addGestureRecognizer:tap];

et sélecteur

-(void)TapTodissmiss{

    [self.txtffld resignFirstResponder];

}
1
Ghanshyam Tomar

Créez simplement une IBOutlet ou un pointeur sur le champ de texte et appelez [textField resignFirstResponder]; où vous le souhaitez.

1
Or Ron

C’est la méthode la plus simple que nous ayons trouvée et qui fonctionne de manière constante. Ajoutez simplement un outil de reconnaissance des gestes du tap sur la vue et vous êtes prêt à partir. 

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

[self.view endEditing:YES];

}

0
Andrew Cook

Pour ma mise en œuvre, [self.view endEditing: YES] ne fonctionnait pas. 

Pour enfin vous assurer que le clavier était masqué, je devais faire de l'une de mes vues le premier intervenant, puis le faire immédiatement démissionner conformément à la fonction ci-dessous:

-(void) hideKeyboardPlease{
   [uiTextTo becomeFirstResponder];
   [uiTextTo resignFirstResponder];
}
0
Lenny

Lorsque cela est possible, la meilleure option consiste à laisser votre UIView hériter de UIButton à la place. 

Il vous suffit de le modifier dans Interface Builder et vous obtiendrez immédiatement les options permettant de créer une action "Retouche à l'intérieur" comme n'importe quel autre bouton. 

Votre vue fonctionnera comme d'habitude car UIButton est toujours une vue, mais vous en serez averti lorsque quelqu'un appuiera dessus. Là tu peux appeler 

[self.view endEditing:YES];

Résigner n'importe quel clavier.

S'il vous plaît noter que si votre vue est un UIScrollView cette solution n'est pas pour vous.

0
Julio Bailon

Mettre à jour

J'ai trouvé un autre moyen simple 

déclarez simplement une propriété: -

@property( strong , nonatomic) UITextfield *currentTextfield;

et un geste de reconnaissance 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égation 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

Créez votre IBOutlet dans le fichier ViewController.h comme ci-dessous:

//YOUR ViewController.h FILE

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    //WIRE THIS WITH YOUR UITextField OBJECT AT YOUR .xib FILE
    IBOutlet UITextField *yourIBOutletUITextField;
}

@end

Ajoutez ceci à votre fichier ViewController.m:

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

comme ci-dessous:

//YOUR ViewController.m FILE

#import "ViewController.h"

@implementation ViewController


//ADD THIS METHOD BELOW
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
     [yourIBOutletUITextField resignFirstResponder];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    }

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end
0
EFE

C'est ce que je fais...

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideAllKeyboards)];
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];

-(void) hideAllKeyboards {
    [textField_1 resignFirstResponder];
    [textField_2 resignFirstResponder];
    [textField_3 resignFirstResponder];
    .
    .
    .
    [textField_N resignFirstResponder];
}
0
Fahim Parkar