iOS-renvoie le clavier en touchant à l'extérieur D'UITextField

je me demande comment faire disparaître le clavier lorsque l'utilisateur touche en dehors d'un UITextField .

416
demandé sur Tamás Sengel 2011-03-15 03:31:21

30 réponses

vous devrez ajouter un UITapGestureRecogniser et l'assigner à la vue, puis appeler demission first responder sur le UITextField sur son sélecteur.

le code:

viewDidLoad

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

[self.view addGestureRecognizer:tap];

Dans dismissKeyboard:

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

(où aTextField est le champ de texte qui est responsable du clavier)

Swift 3 la version ressemble à cela

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)

Pour dismissKeyboard

func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}
720
répondu Jensen2k 2017-11-16 07:29:49

j'ai rassemblé quelques réponses.

utilisez un ivar qui est initialisé pendant viewDidLoad:

UIGestureRecognizer *tapper;

- (void)viewDidLoad
{
    [super viewDidLoad];
    tapper = [[UITapGestureRecognizer alloc]
                initWithTarget:self action:@selector(handleSingleTap:)];
    tapper.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapper];
}

rejeter ce qui est en cours d'édition:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}
168
répondu drewish 2018-03-07 18:42:49

ça, ce serait la façon la plus simple de le faire", 151920920"

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
      [self.view endEditing:YES];// this will do the trick
}

ou

Cette bibliothèque va gérer y compris la barre de défilement le défilement automatique, appuyez sur espace pour masquer le clavier, etc...

https://github.com/michaeltyson/TPKeyboardAvoiding

100
répondu Prasad De Zoysa 2015-04-20 05:38:16

je vois que certaines personnes ont des problèmes en utilisant la méthode UITapGestureRecognizer . La manière la plus simple que j'ai accomplie cette fonctionnalité tout en laissant intact le comportement du robinet de mon bouton existant est d'ajouter une seule ligne à la réponse de @Jensen2k:

[tap setCancelsTouchesInView:NO];

cela a permis à mes boutons existants de continuer à fonctionner sans utiliser la méthode de @Dmitry Sitnikov.

lisez à propos de property ici (cherchez CancelsTouchesInView ): Classe UIGestureRecognizer Référence

Je ne suis pas sûr comment cela fonctionnerait avec les barres de défilement, car je vois que certains ont eu des problèmes avec, mais j'espère que quelqu'un d'autre pourrait tomber dans le même scénario que moi.

82
répondu Qiao Yi 2018-03-23 09:32:26

il est préférable de faire de votre UIView une instance de UIControl (dans interface builder) et de connecter ensuite leur événement TouchUpInside à la méthode dismissKeyboard . Cette méthode IBAction ressemblera à:

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}
55
répondu Dmitry Sitnikov 2018-03-23 08:57:11

version Swift, cela fonctionne en combinaison avec d'autres éléments (comme un UIButton ou un autre UITextField ):

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}
25
répondu Rob 2017-04-02 09:54:06

Que Diriez-vous de ceci: je sais que c'est un vieux post. Il pourrait aider quelqu'un :)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    NSArray *subviews = [self.view subviews];
    for (id objects in subviews) {
        if ([objects isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objects;
            if ([objects isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        } 
    }
}
15
répondu Mr H 2018-04-26 08:14:05

C'est une bonne solution générique:

Objectif-C:

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

Swift:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

basé sur la solution @icodebuster: https://stackoverflow.com/a/18756253/417652

13
répondu eduludi 2017-05-23 12:18:26

je pense que la façon la plus facile (et la meilleure) de faire ceci est de sous-estimer votre vue globale et d'utiliser la méthode hitTest:withEvent pour écouter n'importe quelle touche. Les Touches sur le clavier ne sont pas enregistrées, donc hitTest: withEvent est seulement appelé lorsque vous touch/scroll/swipe/pinch... ailleurs, puis appelez [self endEditing:YES] .

c'est mieux que d'utiliser touchesBegan parce que touchesBegan ne sont pas appelés si vous cliquez sur un bouton en haut de la vue. C'est mieux que UITapGestureRecognizer qui ne peut pas reconnaître un geste défilant par exemple. Il est également préférable d'utiliser un écran dim parce que dans une interface utilisateur complexe et dynamique, vous ne pouvez pas mettre un écran dim partout. De plus, il ne bloque pas les autres actions, vous n'avez pas besoin de taper deux fois pour sélectionner un bouton à l'extérieur (comme dans le cas d'un UIPopover ).

aussi, c'est mieux que d'appeler [textField resignFirstResponder] , parce que vous pouvez avoir beaucoup de champs de texte à l'écran, donc cela fonctionne pour chacun d'eux.

10
répondu Enzo Tran 2018-01-01 07:24:00

Swift 4

configurez votre UIViewController avec cette méthode d'extension une fois E. g in viewDidLoad :

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupHideKeyboardOnTap()
}

et le clavier sera supprimé même en tapant sur le NavigationBar .

import UIKit
extension UIViewController {
    /// Call this once to dismiss open keyboards by tapping anywhere in the view controller
    func setupHideKeyboardOnTap() {
        self.view.addGestureRecognizer(self.endEditingRecognizer())
        self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer())
    }

    /// Dismisses the keyboard from self.view
    private func endEditingRecognizer() -> UIGestureRecognizer {
        let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:)))
        tap.cancelsTouchesInView = false
        return tap
    }
}
8
répondu FBente 2018-01-26 13:09:04

vous pouvez le faire en utilisant le Storyboard dans XCode 6 et au-dessus:



créer l'action de cacher le clavier

ajoutez ceci au fichier d'en-tête de la classe utilisée par votre ViewController:

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>

- (IBAction)dissmissKeyboardOnTap:(id)sender;

@end

puis ajoutez ceci au fichier d'implémentation du même ViewController:

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

ce sera maintenant l'une des "Actions reçues" pour votre scène de scénario-maquette (ViewController):

enter image description here



Crochet jusqu'à l'action de l'utilisateur événement

maintenant vous devez accrocher cette action au geste de l'utilisateur de toucher le clavier.

Important - vous devez convertir le "UIView" qui est contenu dans votre storyboard en UIControl , de sorte qu'il peut recevoir des événements. Sélectionnez la vue dans la hiérarchie de la scène du contrôleur de vue:

enter image description here

...et de changer de classe:

enter image description here

glissez maintenant du petit cercle à côté de l '"action reçue" pour votre scène, dans une partie' vide 'de votre scène (en fait vous glissez le 'Action reçue' Action" à L'UIControl). Vous verrez une sélection d'événements que vous pouvez accrocher à votre action:

enter image description here

sélectionnez l'option "retouche à l'intérieur". Vous avez maintenant accroché L'IBAction que vous avez créé à une action de l'utilisateur de toucher le clavier. Lorsque l'utilisateur coupe le clavier, il le cache.

(NOTE: pour accrocher l'action à l'événement, vous pouvez également faire glisser de l'action reçue directement sur L'UIControl dans la hiérarchie des contrôleurs de votre vue. Il est affiché comme "Contrôle" dans la hiérarchie.)

6
répondu Chris Halcrow 2015-10-16 01:47:40

ce doit être la façon la plus facile de cacher votre clavier en touchant l'extérieur:

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

(de Comment faire pour faire disparaître le clavier lorsque l'utilisateur appuyez sur une autre zone à l'extérieur de textfield? )

6
répondu Maggie Phillips 2017-05-23 12:26:38

si je vous ai bien compris, vous voulez renoncer au clavier en tapant en dehors de textfield mais vous n'avez pas de référence de votre textfield .

Essayez ceci;

  • prenons global textField, appelons-le reftextField
  • Maintenant textFieldDidBeginEditing set référencé champ de texte pour

    - (void) textFieldDidBeginEditing:(UITextField *)textField{
        reftextField = textField;
    }
    
  • Maintenant, vous pouvez heureusement utiliser sur n'importe quelle horloge bouton, (ajoutant un bouton transparent sur Commencer l'édition recomended)

    - (void)dismissKeyboard {
          [reftextField resignFirstResponder];
    }
    
  • ou pour démissionner bouton fait essayez ceci.

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
5
répondu rptwsthi 2013-03-01 14:51:31

Si la vue est intégré dans un UIScrollView , alors vous pouvez utiliser ce qui suit:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

le premier animera l'écran clavier off lorsque la vue de la table est scrollée et le second masquera le clavier comme l'application de messages d'actions.

notez qu'ils sont disponibles sur iOS 7.0 ou plus haut.

4
répondu Joe Masilotti 2014-08-14 13:11:53

juste pour ajouter à la liste ici ma version de comment rejeter un clavier sur le toucher extérieur.

viewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];

n'importe où:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    [textFieldName resignFirstResponder];
    puts("Dismissed the keyboard");
}
3
répondu John Riselvato 2012-07-17 00:50:28

Beaucoup de bonnes réponses ici sur l'utilisation de UITapGestureRecognizer , qui tous casser UITextField 's clair (X) bouton. La solution est de supprimer le reconnaisseur de geste via son délégué:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]];
    BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]];
    return !(touchViewIsButton && touchSuperviewIsTextField);
}

ce n'est pas la solution la plus robuste mais ça marche pour moi.

3
répondu skedastik 2013-11-22 03:59:57

vous pouvez créer la catégorie pour L'uivi et Outrepasser le meathod touchesBegan comme suit.

ça marche très bien pour moi.Et c'est une solution centralisée pour ce problème.

#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.window endEditing:true];
    [super touchesBegan:touches withEvent:event];
}
@end
3
répondu Hiren 2015-10-29 09:12:52

version Swift de la réponse de @Jensen2k:

let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)

func dismissKeyboard() {
    aTextField.resignFirstResponder()
}

One liner

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
3
répondu Syed Asad Ali 2018-01-17 05:38:47

j'ai utilisé Barry exemple pour mon nouveau développement. Il fonctionnait très bien! mais j'ai dû inclure un petit changement, requis pour rejeter le clavier seulement pour le champ text étant édité.

donc, j'ai ajouté à L'exemple de Barry ce qui suit:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    _textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
    _textBeingEdited = nil;
}

aussi, j'ai changé la méthode hideKeyboard comme suit:

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    //UITextField * tf = (UITextField *) sender;
    [_textBeingEdited resignFirstResponder];
}
2
répondu mtorre 2013-08-18 23:01:45

l'Un des plus facile et plus court est d'ajouter ce code à votre viewDidLoad

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];
2
répondu Sudhin Davis 2015-05-07 07:45:43

Swift 4 oneliner

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
2
répondu newDeveloper 2018-07-01 03:13:53

Envoyer un message resignFirstResponder à la textfiled qui l'a mis là. S'il vous plaît voir ce message pour plus d'informations.

1
répondu Ke Sun 2017-05-23 12:10:44

ça fonctionne

dans cet exemple, aTextField est le seul UITextField.... S'il y en a d'autres ou S'il y en a D'autres, il y a un tout petit peu plus à faire.

// YourViewController.h
// ...
@interface YourViewController : UIViewController /* some subclass of UIViewController */ <UITextFieldDelegate> // <-- add this protocol
// ...
@end

// YourViewController.m

@interface YourViewController ()
@property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer;
@end
// ...

@implementation
@synthesize singleTapRecognizer = _singleTapRecognizer;
// ...

- (void)viewDidLoad
{
    [super viewDidLoad];
    // your other init code here
    [self.view addGestureRecognizer:self.singleTapRecognizer];

{

- (UITapGestureRecognizer *)singleTapRecognizer
{
    if (nil == _singleTapRecognizer) {
        _singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)];
        _singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events.
    }
    return _singleTapRecognizer;
}

// Something inside this VC's view was tapped (except the navbar/toolbar)
- (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender
{
    NSLog(@"singleTap");
    [self hideKeyboard:sender];
}

// When the "Return" key is pressed on the on-screen keyboard, hide the keyboard.
// for protocol UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    NSLog(@"Return pressed");
    [self hideKeyboard:textField];
    return YES;
}

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    [aTextField resignFirstResponder];
    NSLog(@"keyboard hidden");
}
1
répondu Barry 2013-06-11 11:55:50

j'ai essayé beaucoup de réponses ici et n'avait pas de chance. Mon outil de reconnaissance des gestes du robinet a toujours fait en sorte que mes UIButtons ne répondaient pas lorsqu'ils étaient sollicités, même lorsque j'ai placé la propriété cancelsTouchesInView de l'outil de reconnaissance des gestes à NO.

C'est ce qui a finalement résolu le problème:

Ont un ivar:

UITapGestureRecognizer *_keyboardDismissGestureRecognizer;

Lorsqu'un champ de texte commence à être édité, définissez le reconnaisseur de geste:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    if(_keyboardDismissGestureRecognizer == nil)
    {
        _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)] autorelease];
        _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;

        [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
    }
}

alors le truc est dans la façon dont vous mettez en place la méthode de classement:

- (void) dismissKeyboard
{
    [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}

- (void) dismissKeyboardSelector
{
    [self.view endEditing:YES];

    [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
    _keyboardDismissGestureRecognizer = nil;
}

je suppose qu'il y a juste quelque chose à propos de faire sortir l'exécution selector de la pile d'exécution touch handling...

1
répondu user1021430 2013-06-14 21:07:33
- (void)viewDidLoad
{
    [super viewDidLoad]; 

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                                                          initWithTarget:self
                                                          action:@selector(handleSingleTap:)];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
    [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer];

    [self.view addGestureRecognizer:singleTapGestureRecognizer];
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    [self.view endEditing:YES];
    [textField resignFirstResponder];
    [scrollView setContentOffset:CGPointMake(0, -40) animated:YES];

}
1
répondu Gaurav Gilani 2014-05-19 07:01:41

ajoutez ce code dans votre ViewController .m fichier :

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
1
répondu aashish tamsya 2015-09-17 11:35:02
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
     view.endEditing(true)

     }
}
1
répondu Phani Sai 2016-04-12 06:10:12

dans ce cas, il peut y avoir l'utilisation ScrollView et ajouté à TextField dans ScrollView et je veux Tap le ScrollView et la vue puis rejeter le clavier. J'ai essayé de créer un code au cas où. Comme ceci,

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:)))
        view.addGestureRecognizer(tapGesture)
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

votre histoire ressemble à ça.

enter image description here

1
répondu Ravi Dhorajiya 2016-06-04 14:16:58

vous pouvez utiliser la méthode UITapGestureRecongnizer pour rejeter le clavier en cliquant à l'extérieur de UITextField. En utilisant cette méthode chaque fois que l'utilisateur cliquera à l'extérieur de UITextField alors clavier sera rejeté. Ci-dessous l'extrait de code pour l'utiliser.

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

    [self.view addGestureRecognizer:tap];


//Method
- (void) dismissk
{
    [abctextfield resignFirstResponder];
    [deftextfield resignFirstResponder];

}
1
répondu Nirzar Gandhi 2016-08-16 09:58:53
  • Ensemble des champs de texte délégué en vue a la charge:

    override func viewDidLoad() 
    {
      super.viewDidLoad()
      self.userText.delegate = self
    }
    
  • ajouter cette fonction:

    func textFieldShouldReturn(userText: UITextField!) -> Bool 
    {
     userText.resignFirstResponder()
     return true;
    }
    
1
répondu seggy 2016-09-06 11:06:18