Mi chiedo come far sparire la tastiera quando l'utente tocca al di fuori di un UITextField
.
Mi chiedo come far sparire la tastiera quando l'utente tocca al di fuori di un UITextField
.
Risposte:
Dovrai aggiungere un UITapGestureRecogniser
e assegnarlo alla vista, quindi chiamare dimetti primo risponditore sul UITextField
relativo selettore.
Il codice:
In viewDidLoad
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
Nella tastiera tastiera:
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
}
(Dov'è aTextField
il campo di testo responsabile della tastiera)
La versione di Swift 3 si presenta così
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)
Per chiudere la tastiera
@objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
aTextField.resignFirstResponder()
}
[aTextField resignFirstResponder]
sarebbe [self.view endEditing:YES];
necessario un riferimento al campo di testo e funzionerà per più campi di testo
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)]];
[tap setCancelsTouchesInView:NO];
per la risposta di @qiaoyi; Ho avuto un problema con una tabella che non rispondeva alle selezioni di riga. 5 anni dopo, spero che questo aiuti qualcun altro.
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
Ho ottenuto alcune risposte.
Usa un ivar che viene inizializzato durante viewDidLoad:
UIGestureRecognizer *tapper;
- (void)viewDidLoad
{
[super viewDidLoad];
tapper = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleSingleTap:)];
tapper.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapper];
}
Ignora ciò che mai sta attualmente modificando:
- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
[self.view endEditing:YES];
}
Controlla questo, questo sarebbe il modo più semplice per farlo,
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];// this will do the trick
}
O
Questa libreria gestirà tra cui lo scorrimento automatico della barra di scorrimento, toccare lo spazio per nascondere la tastiera, ecc ...
Vedo che alcune persone hanno problemi con il UITapGestureRecognizer
metodo. Il modo più semplice con cui ho realizzato questa funzionalità pur mantenendo intatto il comportamento di tocco del mio pulsante esistente è l'aggiunta di una sola riga alla risposta di @ Jensen2k:
[tap setCancelsTouchesInView:NO];
Ciò ha permesso ai miei pulsanti esistenti di funzionare ancora senza usare il metodo di @Dmitry Sitnikov.
Leggi property
qui (cerca CancelsTouchesInView
): Riferimento classe UIGestureRecognizer
Non sono sicuro di come funzionerebbe con le barre di scorrimento, poiché vedo che alcuni hanno avuto problemi, ma spero che qualcun altro possa imbattersi nello stesso scenario che ho avuto.
UIImageView
, aggiungi [imageView setUserInteractionEnabled:NO];
e "fai clic" su di essa, facendo funzionare questo metodo.
È meglio creare UIView
un'istanza di UIControl
(in builder di interfaccia) e quindi connettere il loro TouchUpInside
evento al dismissKeyboard
metodo. Questo IBAction
metodo sarà simile a:
- (IBAction)dismissKeyboard:(id)sender {
[aTextBox resignFirstResponder];
}
UITapGestureRecognizer
interferito toccando i pulsanti all'interno della vista). touchesEnded
non ha funzionato perché c'era un UIScrollView
pasticcio con la catena di responder.)
Swift 4
Imposta il tuo UIViewController
con questo metodo di estensione una volta, ad esempio in viewDidLoad
:
override func viewDidLoad() {
super.viewDidLoad()
self.setupHideKeyboardOnTap()
}
e la tastiera verrà chiusa anche toccando il 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
}
}
Versione rapida, funziona in combinazione con altri elementi (come uno UIButton
o l'altro UITextField
):
override func viewDidLoad() {
super.viewDidLoad()
let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
tapper.cancelsTouchesInView = false
view.addGestureRecognizer(tapper)
}
self
piuttosto cheself.view
canclesTouchesInView
è una proprietà utile da usare. Grazie.
c#
. FYI Quel punto e virgola è consentito dalla sintassi, non è necessario.
Che ne dici di questo: so che questo è un vecchio post. Potrebbe aiutare qualcuno :)
- (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];
}
}
}
}
Questa è una buona soluzione generica:
Objective-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)
}
Basato sulla soluzione @icodebuster: https://stackoverflow.com/a/18756253/417652
Swift 4 oneliner
view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Penso che il modo più semplice (e migliore) per farlo sia quello di sottoclassare la tua visione globale e usare il hitTest:withEvent
metodo per ascoltare qualsiasi tocco. I tocchi sulla tastiera non sono registrati, quindi hitTest: withEvent viene chiamato solo quando tocchi / scorri / scorri / pizzica ... da qualche altra parte, quindi chiama[self endEditing:YES]
.
È meglio dell'uso touchesBegan
perché touchesBegan
non vengono chiamati se si fa clic su un pulsante nella parte superiore della vista. È meglio di ciò UITapGestureRecognizer
che non può riconoscere un gesto di scorrimento, ad esempio. È anche meglio dell'uso di uno schermo scuro perché in un'interfaccia utente complessa e dinamica, non è possibile posizionare lo schermo scuro ovunque. Inoltre, non blocca altre azioni, non è necessario toccare due volte per selezionare un pulsante all'esterno (come nel caso di aUIPopover
).
Inoltre, è meglio che chiamare [textField resignFirstResponder]
, perché potresti avere molti campi di testo sullo schermo, quindi questo funziona per tutti.
Questo deve essere il modo più semplice per nascondere la tastiera toccando all'esterno:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
(da Come chiudere la tastiera quando l'utente tocca un'altra area fuori dal campo di testo? )
Se la vista è incorporata affatto in a, UIScrollView
è possibile utilizzare quanto segue:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
Il primo animerà la tastiera fuori dallo schermo quando si fa scorrere la vista della tabella e il secondo nasconderà la tastiera come l'app Messaggi.
Si noti che sono disponibili su iOS 7.0 o versioni successive.
Puoi farlo usando lo Storyboard in XCode 6 e versioni successive:
Aggiungi questo al file di intestazione della classe utilizzata da ViewController:
@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>
- (IBAction)dissmissKeyboardOnTap:(id)sender;
@end
Quindi aggiungilo al file di implementazione dello stesso ViewController:
- (IBAction)dissmissKeyboardOnTap:(id)sender{
[[self view]endEditing:YES];
}
Questa sarà ora una delle "Azioni ricevute" per la scena dello storyboard (ad esempio ViewController):
Ora devi collegare questa azione al gesto dell'utente di toccare la tastiera.
Importante: devi convertire "UIView" contenuto nello storyboard in UIControl , in modo che possa ricevere eventi. Seleziona la vista dalla gerarchia della scena del controller di visualizzazione:
... e cambia classe:
Ora trascina dal piccolo cerchio accanto all '"azione ricevuta" per la tua scena, su una parte "vuota" della scena (in realtà stai trascinando l' "Azione ricevuta" su UIControl). Ti verrà mostrata una selezione di eventi a cui puoi collegare la tua azione a:
Seleziona l'opzione "Ritocca dentro". Ora hai agganciato l'IBAction che hai creato a un'azione dell'utente di toccare la tastiera. Quando l'utente tocca la tastiera, ora sarà nascosta.
(NOTA: per agganciare l'azione all'evento, puoi anche trascinare dall'azione ricevuta direttamente su UIControl nella gerarchia dei controller di visualizzazione. Viene visualizzato come 'Controllo' nella gerarchia.)
Se ti ho capito bene, vuoi dimettersi mentre tocchi la tastiera, textfield
ma non hai riferimenti ai tuoi textfield
.
Prova questo;
reftextField
Ora nel textFieldDidBeginEditing
campo di testo di riferimento impostato su
- (void) textFieldDidBeginEditing:(UITextField *)textField{
reftextField = textField;
}
Ora puoi tranquillamente utilizzarlo su qualsiasi pulsante orologio (aggiungendo un pulsante trasparente su iniziare la modifica consigliata)
- (void)dismissKeyboard {
[reftextField resignFirstResponder];
}
O per dimettersi il pulsante Fine provare questo.
//for resigning on done button
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
Solo per aggiungere all'elenco qui la mia versione di come eliminare una tastiera al tocco esterno.
viewDidLoad:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];
Dovunque:
-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
[textFieldName resignFirstResponder];
puts("Dismissed the keyboard");
}
Un sacco di ottime risposte qui sull'uso UITapGestureRecognizer
di - tutti i quali UITextField
cancella il pulsante (X) di interruzione . La soluzione è sopprimere il riconoscimento dei gesti tramite il suo delegato:
- (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);
}
Non è la soluzione più robusta ma funziona per me.
return !touchViewIsButton
. Immagino che qualsiasi altro pulsante che debba chiudere la tastiera dovrebbe farlo nelle loro azioni. Inoltre, TouchUpInside potrebbe non essere chiamato quando il layout cambia al momento dell'eliminazione della tastiera.
Puoi creare una categoria per UiView e sovrascrivere i tocchiBegan meathod come segue.
Funziona bene per me ed è la soluzione centralizzata per questo problema.
#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.window endEditing:true];
[super touchesBegan:touches withEvent:event];
}
@end
Versione rapida della risposta di @ Jensen2k:
let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)
func dismissKeyboard() {
aTextField.resignFirstResponder()
}
Una fodera
self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
Ho usato l'esempio di Barry per il mio nuovo sviluppo. Ha funzionato alla grande! ma ho dovuto includere una leggera modifica, necessaria per chiudere la tastiera solo per il campo di testo che si sta modificando.
Quindi, ho aggiunto a Barry l'esempio seguente:
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
_textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
_textBeingEdited = nil;
}
Inoltre, ho cambiato il metodo hideKeyboard come segue:
- (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];
}
Uno dei modi più semplici e brevi è aggiungere questo codice al tuo viewDidLoad
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
initWithTarget:self.view
action:@selector(endEditing:)]];
Ho provato molte delle risposte qui e non ho avuto fortuna. Il mio riconoscimento dei gesti dei tocchi faceva sempre sì UIButtons
che non rispondessi quando toccato, anche quando imposto ilcancelsTouchesInView
proprietà del riconoscimento dei gesti su NO.
Questo è ciò che alla fine ha risolto il problema:
Avere un Ivar:
UITapGestureRecognizer *_keyboardDismissGestureRecognizer;
Quando un campo di testo inizia la modifica, imposta il riconoscimento gesti:
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
if(_keyboardDismissGestureRecognizer == nil)
{
_keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(dismissKeyboard)] autorelease];
_keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
}
}
Quindi il trucco è come impostare il dismissKeyboard
metodo:
- (void) dismissKeyboard
{
[self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}
- (void) dismissKeyboardSelector
{
[self.view endEditing:YES];
[self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
_keyboardDismissGestureRecognizer = nil;
}
Immagino che ci sia qualcosa nell'ottenere l' dismissKeyboardSelector
esecuzione dallo stack di esecuzione della gestione del tocco ...
Invia un messaggio resignFirstResponder
al file di testo che lo mette lì. Si prega di consultare questo post per ulteriori informazioni.
In questo esempio, aTextField è l'unico UITextField .... Se ce ne sono altri o UITextViews, c'è ancora qualcosa da fare.
// 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");
}
- (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];
}
Aggiungi questo codice nel tuo file ViewController.m :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
In questo caso, è possibile utilizzare ScrollView e aggiunto a TextField
ScrollView e voglio Toccare ScrollView
e Visualizza quindi Ignora la tastiera. Ho provato a creare un codice di esempio per ogni evenienza. Come questo,
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.
}
}
Il tuo storyboard Guarda che proprio come.
È possibile utilizzare il metodo UITapGestureRecongnizer per eliminare la tastiera facendo clic all'esterno di UITextField. Usando questo metodo ogni volta che l'utente farà clic al di fuori di UITextField, la tastiera verrà eliminata. Di seguito è riportato lo snippet di codice per usarlo.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(dismissk)];
[self.view addGestureRecognizer:tap];
//Method
- (void) dismissk
{
[abctextfield resignFirstResponder];
[deftextfield resignFirstResponder];
}