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
.
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()
}
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];
}
ç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...
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.
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];
}
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)
}
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];
}
}
}
}
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
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.
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
}
}
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):
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:
...et de changer de classe:
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:
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.)
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];
}
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; }
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.
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");
}
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.
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
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:"))
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];
}
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:)]];
Swift 4 oneliner
view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Envoyer un message resignFirstResponder
à la textfiled qui l'a mis là. S'il vous plaît voir ce message pour plus d'informations.
ç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");
}
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...
- (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];
}
ajoutez ce code dans votre ViewController .m fichier :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first{
view.endEditing(true)
}
}
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.
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];
}
-
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; }