Come si elimina la tastiera quando si modifica un UITextField


181

So che devo dire al mio UITextField di dare le dimissioni dal primo risponditore quando desidero smantellare la tastiera, ma non sono sicuro di sapere quando l'utente ha premuto il tasto "Fine" sulla tastiera. C'è una notifica che posso cercare?


2
[self.view endEditing: SÌ]; in tocchi iniziati delegare è la soluzione migliore
Zar E Ahmer,

Risposte:


351

Ho impostato il delegato della UITextFieldmia ViewControllerclasse.

In quella classe ho implementato questo metodo come segue:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}

Vedi l'esempio sopra ... collega che l'utilizzo di IntefaceBuilder all'azione su qualunque cosa tu stia usando come controller ... ogni volta che l'utente elimina il sistema di immissione del testo (preme fatto), questo verrà invocato ...
Jason Coco

2
Entrambe funzioneranno: il campo di testo invia la sua azione quando l'utente preme il tasto Return ("Fatto", qualunque sia) e invia anche il suo delegato -textFieldShouldReturn :.
Noah Witherspoon,

A proposito: questo funziona anche con un UISearchBar. Ad esempio, nel mio codice avevo un membro IBOutlet searchBarTusb; Quando è stato cliccato il mio 'tasto invio' (UIReturnKeySearch), - (void) searchBarSearchButtonClicked :, ho messo la dichiarazione [searchBarTusb resignFirstResponder]; Si noti inoltre che la 'chiave di ritorno' è stata impostata nel NIB utilizzando Interface Builder.
Mobibob,

Perché tornare NOinvece di YES?
Iulian Onofrei

@IulianOnofrei Il comportamento predefinito del pulsante di ritorno è quello di aggiungere un ritorno di linea e mantenere la tastiera sullo schermo. Restituendo NOsi evita di aggiungere una riga di ritorno al testo.
Kubi,

47

Se si collega l'evento DidEndOnExit del campo di testo a un'azione (IBAction) in InterfaceBuilder, verrà inviato un messaggio quando l'utente elimina la tastiera (con il tasto Invio) e il mittente sarà un riferimento all'UITextField che ha generato l'evento.

Per esempio:

-(IBAction)userDoneEnteringText:(id)sender
{
    UITextField theField = (UITextField*)sender;
    // do whatever you want with this text field
}

Quindi, in InterfaceBuilder, collega l'evento DidEndOnExit del campo di testo a questa azione sul controller (o qualunque cosa tu stia utilizzando per collegare eventi dall'interfaccia utente). Ogni volta che l'utente inserisce il testo e chiude il campo di testo, al controller verrà inviato questo messaggio.


L'unico evento che sembra funzionare potrebbe essere textFieldDidEndEditing, che indica che viene inviato solo dopo che UITextField si è dimesso dallo stato del primo risponditore. Come faccio a sapere quando devo dimettermi dallo stato di primo soccorritore?
kubi,

Mi dispiace per la terminologia ... non è una notifica effettiva (evento) ... Ho intenzione di modificare la mia risposta con un rapido esempio e una spiegazione, quindi vedi che :)
Jason Coco,

1
Per chiarire questa risposta, textField invia l'evento "Did End On Exit" quando premi il tasto Invio, quindi è quello che devi collegare al tuo controller. Penso che questo metodo sia più semplice di quello che ho descritto sopra.
Kubi,

2
potresti modificare questa risposta in modo che menzioni QUALE evento da cablare, per favore? Questo è ovviamente più bello che impostare il delegato.
Dan Rosenstark,

1
Vuoi votare questa risposta, ma non puoi fino a quando non menziona l'evento DidEndOnExit. Qualcuno con privilegi di modifica si prega di apportare la modifica se l'OP non lo farà?
James Hart,

32

Puoi anche creare un metodo nel tuo controller

 -(IBAction)editingEnded:(id)sender{
    [sender resignFirstResponder]; 
}

e quindi in Connection Inspector in IB connect Evento "Did End On Exit".


1
Questo è quasi errato, o almeno manca il punto. Iscrivendosi DidEndOnExitall'evento, non è necessario chiamare resignFirstResponder. Puoi provarlo inserendo un breakpoint simbolico [UIResponder resignFirstResponder]. Si noti che anche se non si chiama resignFirstResponder, viene comunque chiamato dal sistema. Questo è spiegato negli eccellenti libri di Matt Neuburg: apeth.com/iOSBook/…
Chris Conover,

19

kubi, grazie. Il tuo codice ha funzionato. Giusto per essere esplicito (per i neofiti come) mentre dici che devi impostare UITextField's delegatein modo che sia uguale al ViewController in cui risiede il campo di testo. Puoi farlo ovunque tu voglia. Ho scelto il viewDidLoadmetodo

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}

Se hai aggiunto un campo di testo allo storyboard o al NIB, puoi anche impostare il campo di testo delegatelì. Non è necessario farlo a livello di codice, come dimostrato sopra. Entrambi gli approcci funzionano bene.
Rob,

18

Ecco un trucco per ottenere il comportamento di licenziamento automatico della tastiera senza alcun codice. Nel pennino, modificare l'oggetto proxy First Responder nella finestra di ispezione Identity, aggiungendo una nuova azione first responder; chiamiamolo dummy:. Ora aggancia l'evento Did End on Exit del campo di testo dummy:all'azione dell'oggetto proxy First Responder. Questo è tutto! Poiché l'evento Did End on Exit del campo di testo ora ha una coppia azione-bersaglio, il campo di testo elimina automaticamente la sua tastiera quando l'utente tocca Return; e poiché non vi è alcuna penalità per non aver trovato un gestore per un messaggio inviato nella catena di risponditori, l'app non si arresta in modo anomalo anche se non è stata implementata alcuna applicazione dummy:.


@matt Ho scoperto che SE aggiungo un unfind segue e connetto l'evento didEndOnExit ALLORA il svolgimento segue verrà attivato premendo Invio. Senza la connessione dell'evento il seguito non viene attivato. Ottimo ma Huh? Qualche commento? A proposito: ho i tuoi libri Swift (finito) e iOS10 (al cap. 6). Mi hanno aiutato moltissimo!
Verticon,

@Verticon la domanda e la risposta non hanno nulla a che fare con segues, quindi non capisco il problema ... :( si tratta puramente di un licenziamento della tastiera
matt

@matt Siamo spiacenti, amico. Stavo appoggiando le spalle perché 1) Mi sono imbattuto in questo thread mentre mi occupavo di come gestire la chiave di ritorno di UITextField; e 2) è stata un'occasione per interagire con te (grazie per i libri). Non c'è "problema". Solo una mancanza di comprensione da parte mia sul perché / come funziona come funziona.
Verticon,

@Verticon Chiedo scusa per non essere stato in grado di aiutare. Sentiti libero di formulare una nuova domanda con maggiori informazioni (progetto demo?) E fammi notare, se posso esserti utile.
matt


11

Basta aggiungere

[textField endEditing:YES];

dove si desidera disabilitare la tastiera e visualizzare la vista selettore.


10

In Swift puoi scrivere un'IBAction nel controller e impostare l' evento Did End On Exit del campo di testo su quell'azione

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}

5

Swift 4.2 e funzionerà al 100%

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    // hide key board when the user touches outside keyboard

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    // user presses return key

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

4

Puoi anche usare

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

   [self.yourTextField resignFirstResponder];

  }

Il migliore se hai molti Uitextfields:

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

2

Ecco cosa ho dovuto fare per farlo funzionare, e penso che sia necessario per chiunque abbia un tastierino numerico per una tastiera (o qualsiasi altro senza un pulsante fatto:

  1. Ho cambiato l'UIView in ViewController in UIControl.
  2. Ho creato una funzione chiamata

    -(IBAction)backgroundIsTapped:(id)sender

Questo è stato anche definito nel file .h.

Successivamente, mi sono collegato al bit 'touch down' per ViewController in Interface Builder.

Nella funzione 'background is tapped', ho messo questo:

    [answerField resignFirstResponder];

Ricorda solo di cambiare 'answerField' con il nome di UITextField da cui vuoi rimuovere la tastiera (ovviamente assicurati che UITextField sia definito come sotto :)

    IBOutlet UITextField * <nameoftextfieldhere>;

So che questo argomento probabilmente è morto molto tempo fa ... ma spero che questo possa aiutare qualcuno, da qualche parte!


..ma non funziona così bene se l'utente tocca un altro controllo.
Ragnarius,

2

Noterai che il metodo "textFieldShouldReturn" fornisce l'oggetto campo di testo che ha premuto il tasto DONE. Se si imposta il TAG è possibile attivare quel campo di testo. Oppure puoi tenere traccia e confrontare il puntatore dell'oggetto con un valore del membro memorizzato dal suo creatore.

Il mio approccio è così per uno studio autonomo:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    bool fDidResign = [textField resignFirstResponder];

    NSLog(@"%s: did %resign the keyboard", __FUNCTION__, fDidResign ? @"" : @"not ");

    return fDidResign;
}

Nel frattempo, ho inserito il test di "convalida" che nega le dimissioni che seguono. È solo a scopo illustrativo, quindi se l'utente digita NO! nel campo, non verrà respinto. Il comportamento era come volevo, ma la sequenza di output non era come mi aspettavo.

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    if( [[textField text] isEqualToString:@"NO!"] ) {
        NSLog(@"%@", textField.text);
        return NO;
    } else {
        return YES;
    }
}

Di seguito è riportato il mio output NSLog per questo rifiuto seguito dall'accettazione. Noterai che sto restituendo il risultato delle dimissioni, ma mi aspettavo che restituisse FALSO a me per riferire al chiamante ?! Oltre a ciò, ha il comportamento necessario.

13.313 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd [109: 207] NO!
13.333 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: ha rassegnato le dimissioni dalla tastiera
59.891 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewController doneEditText]: NO
59.928 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: ha rassegnato le dimissioni dalla tastiera

1
puoi spiegare se restituisco NO o SÌ in entrambi i casi accadono le stesse cose, quindi quale necessità di restituire sì in textFieldShould Restituisci il metodo delegato
K. Jaiswal

1

Ecco un modo abbastanza semplice per terminare l'edizione con il tasto Invio o un tocco in background.

Nel builder Interface, incorporare i campi in una vista della classe UIFormView

Cosa significa questa classe:

  • Si collega automaticamente come delegato dei campi (sveglio dal pennino o aggiunto manualmente)
  • Conservare un riferimento sul campo modificato corrente
  • Ignora la tastiera al ritorno o tocca in background

Ecco il codice:

Interfaccia

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

-(BOOL)textFieldValueIsValid:(UITextField*)textField;
-(void)endEdit;

@end

Implementazione

#import "UIFormView.h"

@implementation UIFormView
{
    UITextField* currentEditingTextField;
}

// Automatically register fields

-(void)addSubview:(UIView *)view
{
    [super addSubview:view];
    if ([view isKindOfClass:[UITextField class]]) {
        if ( ![(UITextField*)view delegate] ) [(UITextField*)view setDelegate:self];
    }
}

// UITextField Protocol

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentEditingTextField = textField;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    currentEditingTextField = NULL;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self endEdit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if ([self textFieldValueIsValid:textField]) {
        [self endEdit];
        return YES;
    } else {
        return NO;
    }
}

// Own functions

-(void)endEdit
{
    if (currentEditingTextField) {
        [currentEditingTextField endEditing:YES];
        currentEditingTextField = NULL;
    }
}


// Override this in your subclass to handle eventual values that may prevent validation.

-(BOOL)textFieldValueIsValid:(UITextField*)textField
{
    return YES;
}

@end
  • Sottoclassando il modulo e sovrascrivendo il textFieldValueIsValid:metodo, è possibile evitare la fine dell'edizione se il valore non è corretto per il campo dato.

  • Se un campo ha un delegato impostato in Interface Builder, il modulo non lo modifica. Non vedo molte ragioni per impostare un delegato diverso in un determinato campo, ma perché no ...

Esistono molti modi per migliorare questa classe di visualizzazione dei moduli: allegare un delegato, eseguire alcuni layout, gestire quando le tastiere coprono un campo (utilizzando il frame currentEditingTextField), avviare automaticamente l'edizione per il campo successivo, ...

Personalmente lo tengo nel mio framework e lo faccio sempre sottoclasse per aggiungere funzionalità, è abbastanza spesso utile "così com'è".

Spero che possa aiutare. Saluti a tutti


1
Lezione utile. Un piccolo punto, non dovresti aggiungere il prefisso alle tue classi con "UI". In goal-c dovresti usare il tuo prefisso ("TL"?), In Swift, non usare nulla.
Kubi,

Grazie @kubi. Giusto. È MF nel mio framework, come MooseFactory;)
Moose,

1

se vuoi tutte le modifiche in un UIViewController puoi usare.

[[self view]endEditing:YES];

e se vuoi scartare una tastiera per tastiera UITextField perticolare, usa.

1.aggiungi delegato nel tuo viewcontroller.h

<UITextFieldDelegate>
  1. rendere la delega impossibile per il tuo campo di testo.

    self.yourTextField.delegate = self;

  2. aggiungi questo metodo al tuo viewcontroller.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; restituire SÌ;}


1

Impostare programmaticamente il delegato di UITextField in swift 3

Implementa UITextFieldDelegate nel tuo file ViewController.Swift (ad es. Classe ViewController: UIViewController, UITextFieldDelegate {)

 lazy var firstNameTF: UITextField = {

    let firstname = UITextField()
    firstname.placeholder = "FirstName"
    firstname.frame = CGRect(x:38, y: 100, width: 244, height: 30)
    firstname.textAlignment = .center
    firstname.borderStyle = UITextBorderStyle.roundedRect
    firstname.keyboardType = UIKeyboardType.default
    firstname.delegate = self
    return firstname
}()

lazy var lastNameTF: UITextField = {

    let lastname = UITextField()
    lastname.placeholder = "LastName"
    lastname.frame = CGRect(x:38, y: 150, width: 244, height: 30)
    lastname.textAlignment = .center
    lastname.borderStyle = UITextBorderStyle.roundedRect
    lastname.keyboardType = UIKeyboardType.default
    lastname.delegate = self
    return lastname
}()

lazy var emailIdTF: UITextField = {

    let emailid = UITextField()
    emailid.placeholder = "EmailId"
    emailid.frame = CGRect(x:38, y: 200, width: 244, height: 30)
    emailid.textAlignment = .center
    emailid.borderStyle = UITextBorderStyle.roundedRect
    emailid.keyboardType = UIKeyboardType.default
    emailid.delegate = self
    return emailid
}()

// Mark: - gestione del delegato textField ..

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    if textField == firstNameTF {

        lastNameTF.becomeFirstResponder()
    }

    else if textField == lastNameTF {

        emailIdTF.becomeFirstResponder()
    }
    else {
        view.emailIdTF(true)
    }
    return true
}

0

Crea una funzione hidekeyboard e collegala al campo di testo nel file .xib e seleziona DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Se hai creato la vista utilizzando Interface Builder, utilizza quanto segue Basta creare un metodo,

-(IBAction)dismissKeyboard:(id)sender
{
[sender resignFirstResponder];
}

Basta fare clic con il tasto destro del mouse sul campo di testo nella vista, impostare l'evento come Did End on Exit e collegarlo al metodo "dismissKeyboard".

La migliore guida per i principianti è "Head First iPhone and iPad Development, 2nd Edition"


0

prova questo

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}

0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}

0

Chiunque cerchi Swift 3

1) Assicurati che il delegato di UITextField sia collegato al ViewController nello Storyboard

2) Implementare UITextFieldDelegate nel file ViewController.Swift (ad es. Class ViewController: UIViewController, UITextFieldDelegate {)

3) Utilizzare il metodo delegato di seguito

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }

0

Ecco come licenzio la tastiera in Swift 4.2 e funziona per me:

    override func viewDidLoad() {
    super.viewDidLoad()

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

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }

-2

Swift 3, iOS 9+

@IBAction private func noteFieldDidEndOnExit(_ sender: UITextField) {}

UPD: Funziona ancora bene per me. Penso che il ragazzo che ha dedicato questa risposta non abbia capito che deve legare questa azione a UITextField nello storyboard.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.