Chiudi la tastiera iOS toccando ovunque usando Swift


409

Ho cercato dappertutto questo, ma non riesco a trovarlo. So come chiudere la tastiera usando Objective-Cma non ho idea di come farlo usando Swift? Qualcuno sa?


9
Come lo stai facendo in Objective-C? Normalmente è una conversione da una sintassi all'altra e raramente si tratta di metodi / convenzioni diversi.
Craig Otis,

5
Non ho scavato in Swift, ma avevo l'impressione che l'API fosse la stessa ...
coreyward

Potresti voler controllare questa risposta .
Ahmad F,

Risposte:


1299
override func viewDidLoad() {
    super.viewDidLoad()

    //Looks for single or multiple taps. 
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")

    //Uncomment the line below if you want the tap not not interfere and cancel other interactions.
    //tap.cancelsTouchesInView = false 

    view.addGestureRecognizer(tap)
}

//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)
}

Ecco un altro modo per eseguire questa attività se si intende utilizzare questa funzionalità in più UIViewControllers:

// Put this piece of code anywhere you like
extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false            
        view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard() {
        view.endEditing(true)
    }
}

Ora in ogni UIViewController, tutto ciò che devi fare è chiamare questa funzione:

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

Questa funzione è inclusa come funzione standard nel mio repository che contiene molte utili estensioni Swift come questa, date un'occhiata: https://github.com/goktugyil/EZSwiftExtensions


19
Dalla Swift 2 nella prima risposta, sostituisci questa riga-> tocca: UITapGestureRecognizer = UITapGestureRecognizer (target: self, action: #selector (MyViewController.dismissKeyboard))
Sam Bellerose

2
interrompe il seguito di tableviewcell su un controller da tavolo
Utku Dalmaz

11
Questa è una delle estensioni più utili che abbia mai incontrato! Grazie! L'unica avvertenza che vorrei estendere è che ciò può interferire didSelectRowAtIndexPath.
Clifton Labrum,

47
Ho appena scoperto questa domanda e implementato quel metodo. Quella cosa con "didSelectRow" di tableView / UICollectionView che non chiamava mi faceva letteralmente impazzire. La soluzione è: è sufficiente aggiungere questo al proprio interno: tap.cancelsTouchesInView = false. Questo mi ha risolto almeno per me. Spero che questo aiuti qualcuno
Quantm

10
"Scopri il mio repository" è il nuovo "Ascolta il mio nuovo mixtape": P
Josh,

118

Una risposta alla tua domanda su come chiudere la tastiera in Xcode 6.1 usando Swift di seguito:

import UIKit

class ItemViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textFieldItemName: UITextField!

    @IBOutlet var textFieldQt: UITextField!

    @IBOutlet var textFieldMoreInfo: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        textFieldItemName.delegate = self
        textFieldQt.delegate = self
        textFieldMoreInfo.delegate = self
    }

                       ...

    /**
     * Called when 'return' key pressed. return NO to ignore.
     */
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }


   /**
    * Called when the user click on the view (outside the UITextField).
    */
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }

}

( Fonte di queste informazioni ).


6
Ottimo pezzo di codice, grazie! touchesBegan era esattamente quello che stavo cercando :)
Lukasz Czerwinski

4
Questo non ha funzionato del tutto per me. Se tocco sulla vista del controller di visualizzazione, funziona. Se tocco un elemento di controllo nella vista, la tastiera non viene chiusa.
user3731622

Questa è la risposta migliore che abbia mai usato finora! Questa risposta dovrebbe essere contrassegnata come corretta. Grazie uomo!
wagng,

Questa è la migliore soluzione che ho visto finora. Piccola nota: in Swift più recente la firma di override è cambiata un po '. Devi aggiungere _ prima dei tocchi: ignora le funzioni touchBegan (_ tocchi: imposta <UITouch>, con evento Event: UIEvent?)
Regis St-Gelais

1
Questo probabilmente dovrebbe essere contrassegnato come corretto. La risposta attualmente accettata rende tutti i pulsanti nella vista non rispondenti quando viene mostrata la tastiera.
Bartek Spitza,

39

Swift 4 funzionante

Crea un interno come di seguito e chiama hideKeyboardWhenTappedAround()nel controller della vista Base.

//
//  UIViewController+Extension.swift
//  Project Name
//
//  Created by ABC on 2/3/18.
//  Copyright © 2018 ABC. All rights reserved.
//

import UIKit

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tapGesture = UITapGestureRecognizer(target: self, 
                         action: #selector(hideKeyboard))
        view.addGestureRecognizer(tapGesture)
    }

    @objc func hideKeyboard() {
        view.endEditing(true)
    }
}

La cosa più importante da chiamare nel controller di visualizzazione di base in modo che non sia necessario chiamare sempre in tutti i controller di visualizzazione.


36

Puoi chiamare

resignFirstResponder()

su qualsiasi istanza di un UIResponder, come un UITextField. Se lo chiami nella vista che sta causando la visualizzazione della tastiera, la tastiera verrà chiusa.


5
In una situazione in cui non si conosce esattamente il primo risponditore, resignFirstResponder () può causare un mucchio di problemi. La risposta di Esq qui sotto (usando view.doneEditing ()) è molto più appropriata
shiser

1
Ogni volta che uso resignFirstResponder sul mio textField, l'app si blocca. Ho provato tutto quello che mi veniva in mente e ho cercato una soluzione sul Web. Niente mi aiuta. Vuoi sapere perché succede?
AugustoQ,

1
Come ha detto Shiser, questa non è la soluzione migliore. inoltre non funziona in tutte le situazioni.
Alix,

21
//Simple exercise to demonstrate, assuming the view controller has a //Textfield, Button and a Label. And that the label should display the //userinputs when button clicked. And if you want the keyboard to disappear //when clicken anywhere on the screen + upon clicking Return key in the //keyboard. Dont forget to add "UITextFieldDelegate" and 
//"self.userInput.delegate = self" as below

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

    @IBOutlet weak var userInput: UITextField!
    @IBAction func transferBtn(sender: AnyObject) {
                display.text = userInput.text

    }
    @IBOutlet weak var display: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

//This is important for the textFieldShouldReturn function, conforming to textfieldDelegate and setting it to self
        self.userInput.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

//This is for the keyboard to GO AWAYY !! when user clicks anywhere on the view
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }


//This is for the keyboard to GO AWAYY !! when user clicks "Return" key  on the keyboard

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

}

touchesBegan ha lavorato per me per terminare la modifica del campo di testo e della visualizzazione del testo. Grazie
Sanju,

Questo è quello che uso, semplice. Rimuovi anche i codici non correlati per concentrarti sulla soluzione.
John Doe,

19

per Swift 3 è molto semplice

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

se si desidera nascondere la tastiera premendo il tasto INVIO

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

ma nel secondo caso dovrai anche passare i delegati da tutti i campi di testo al ViewController nel Main.Storyboard


Ottengo unrecognized selector sent to instancecon questo codice.
Haring10,

11

Swift 3: il modo più semplice per chiudere la tastiera:

  //Dismiss keyboard method
    func keyboardDismiss() {
        textField.resignFirstResponder()
    }

    //ADD Gesture Recignizer to Dismiss keyboard then view tapped
    @IBAction func viewTapped(_ sender: AnyObject) {
        keyboardDismiss()
    }

    //Dismiss keyboard using Return Key (Done) Button
    //Do not forgot to add protocol UITextFieldDelegate 
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        keyboardDismiss()

        return true
    }

1
Sono abbastanza sicuro che la chiamata view.endEditing (true) sia più semplice in quanto non richiede che tu memorizzi una variabile o supponga di avere solo un campo di testo.
Glenn Howes,

10

La risposta di Dash è corretta e preferita. Un approccio più "terra bruciata" è quello di chiamare view.endEditing(true). Ciò causa viewe tutte le sue visualizzazioni resignFirstResponder. Se non hai un riferimento alla vista che desideri ignorare, questa è una soluzione confusa ma efficace.

Nota che personalmente penso che dovresti avere un riferimento alla vista che vorresti dimettersi dal primo soccorritore. .endEditing(force: Bool)è un approccio barbaro; per favore non usarlo.


10

bastano 5 veloci solo due righe. Aggiungi nel tuo viewDidLoaddovrebbe funzionare.

 let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
 view.addGestureRecognizer(tapGesture)

Se il gesto del tuo tocco ha bloccato altri tocchi, quindi aggiungi questa riga:

tapGesture.cancelsTouchesInView = false

La soluzione molto semplice ed elegante :), dovrebbe essere la risposta qui.
Joseph Astrahan,

9

Nello storyboard:

  1. seleziona TableView
  2. dal lato destro, seleziona la finestra di ispezione degli attributi
  3. nella sezione tastiera: seleziona la modalità di eliminazione desiderata

non riesci a trovare quell'elemento, dove si trova e che aspetto ha? Sono nell'ispettore degli attributi di un campo di testo
Ethan Parker,

Devi guardare TableView non TextField
zevij

9

Swift 3:

Estensione con Selectorparametro come per essere in grado di fare cose aggiuntive nella funzione di eliminazione e cancelsTouchesInViewprevenire distorsioni con tocchi su altri elementi della vista.

extension UIViewController {
    func hideKeyboardOnTap(_ selector: Selector) {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: selector)
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
}

Uso:

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardOnTap(#selector(self.dismissKeyboard))
}

func dismissKeyboard() {
    view.endEditing(true)
    // do aditional stuff
}

9

Usa IQKeyboardmanager che ti aiuterà a risolvere facilmente .....

/////////////////////////////////////////

! [come disabilitare la tastiera ..] [1]

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

   @IBOutlet weak var username: UITextField!
   @IBOutlet weak var password: UITextField!

   override func viewDidLoad() {
      super.viewDidLoad() 
      username.delegate = self
      password.delegate = self
      // Do any additional setup after loading the view, typically from a nib.
   }

   override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   }

   func textFieldShouldReturn(textField: UITextField!) -> Bool // called when   'return' key pressed. return NO to ignore.
   {
      textField.resignFirstResponder()
      return true;
   }

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

8

Ho trovato che la soluzione migliore includeva la risposta accettata da @Esqarrouth, con alcune modifiche:

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboardView")
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    func dismissKeyboardView() {
        view.endEditing(true)
    }
}

La linea tap.cancelsTouchesInView = falseera critica: assicura che UITapGestureRecognizernon impedisca ad altri elementi della vista di ricevere l'interazione dell'utente.

Il metodo è dismissKeyboard()stato cambiato in leggermente meno elegante dismissKeyboardView(). Questo perché nella base di codice abbastanza vecchia del mio progetto, ci sono state numerose volte in cui è dismissKeyboard()stato già utilizzato (immagino che ciò non sia insolito), causando problemi al compilatore.

Quindi, come sopra, questo comportamento può essere abilitato nei singoli controller di visualizzazione:

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

7

Se si utilizza una vista di scorrimento, potrebbe essere molto più semplice.

Basta selezionare Dismiss interactivelynello storyboard.


7

In Swift 4, aggiungi @objc:

Nel viewDidLoad:

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

Funzione:

@objc func dismissKeyboard() {
  view.endEditing(true)
}

7

Aggiungi questa estensione al tuo ViewController:

  extension UIViewController {
// Ends editing view when touches to view 
  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    self.view.endEditing(true)
  }
}

6

Per espandere la risposta di Esqarrouth , uso sempre quanto segue per chiudere la tastiera, specialmente se la classe da cui sto eliminando la tastiera non ha una viewproprietà e / o non è una sottoclasse diUIView .

UIApplication.shared.keyWindow?.endEditing(true)

E, per comodità, la seguente estensione alla UIApplcationclasse:

extension UIApplication {

    /// Dismisses the keyboard from the key window of the
    /// shared application instance.
    ///
    /// - Parameters:
    ///     - force: specify `true` to force first responder to resign.
    open class func endEditing(_ force: Bool = false) {
        shared.endEditing(force)
    }

    /// Dismisses the keyboard from the key window of this 
    /// application instance.
    ///
    /// - Parameters:
    ///     - force: specify `true` to force first responder to resign.
    open func endEditing(_ force: Bool = false) {
        keyWindow?.endEditing(force)
    }

}

5
  import UIKit

  class ItemViewController: UIViewController, UITextFieldDelegate {

  @IBOutlet weak var nameTextField: UITextField!

    override func viewDidLoad() {
           super.viewDidLoad()
           self.nameTextField.delegate = self
     }

    // Called when 'return' key pressed. return NO to ignore.

    func textFieldShouldReturn(textField: UITextField) -> Bool {

            textField.resignFirstResponder()
             return true
     }

 // Called when the user click on the view (outside the UITextField).

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

5

Come programmatore principiante può essere fonte di confusione quando le persone producono risposte più qualificate e non necessarie ... Non devi fare nessuna delle cose complicate mostrate sopra! ...

Ecco l'opzione più semplice ... Nel caso in cui la tua tastiera appaia in risposta al campo di testo - All'interno della tua funzione touch screen aggiungi semplicemente la funzione resignFirstResponder . Come mostrato di seguito - la tastiera si chiuderà perché viene rilasciato il primo risponditore (uscendo dalla catena di risponditori) ...

override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
    MyTextField.resignFirstResponder()
}

5

Ho usato IQKeyBoardManagerSwift per la tastiera. è facile da usare. basta aggiungere il pod "IQKeyboardManagerSwift"

Importa IQKeyboardManagerSwift e scrivi il codice su didFinishLaunchingWithOptionsin AppDelegate.

///add this line 
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true

4

Questa fodera si dimette dalla tastiera da tutti (tutti) gli UITextField in una vista UIV

self.view.endEditing(true)

4

Solo una riga di codice nel viewDidLoad()metodo:

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))

4

In breve tempo puoi usare

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

}

3

Per Swift3

Registrare un riconoscimento eventi in viewDidLoad

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

quindi dobbiamo aggiungere il gesto nella vista nella stessa viewDidLoad.

self.view.addGestureRecognizer(tap)

Quindi è necessario inizializzare il metodo registrato

func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
    view.endEditing(true)
}

1
Grazie per la risposta completa e con le note. Questa è l'unica soluzione che ha funzionato per me.
Zeeshan,

3

Pubblicare come nuova risposta poiché la mia modifica della risposta di @ King-Wizard è stata respinta.

Rendi la tua classe un delegato di UITextField e sostituisci i tocchiBegan.

Swift 4

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self
    }

    //Called when 'return' key is pressed. Return false to keep the keyboard visible.
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        return true
    }

    // Called when the user clicks on the view (outside of UITextField).
    override func touchesBegan(touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

}

2

Puoi anche aggiungere un riconoscitore di gesti di tocco per dare le dimissioni dalla tastiera. : D

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let recognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    backgroundView.addGestureRecognizer(recognizer)
}
    func handleTap(recognizer: UITapGestureRecognizer) {
    textField.resignFirstResponder()
    textFieldtwo.resignFirstResponder()
    textFieldthree.resignFirstResponder()

    println("tappped")
}

2

Un'altra possibilità è semplicemente aggiungere un pulsante grande senza contenuti che si trovano sotto tutte le viste che potresti dover toccare. Dagli un'azione denominata:

@IBAction func dismissKeyboardButton(sender: AnyObject) {
    view.endEditing(true)
}

Il problema con un riconoscimento dei gesti era per me, che catturava anche tutti i tocchi che volevo ricevere da tableViewCells.


2

Se hai altre visualizzazioni che dovrebbero ricevere anche il tocco, devi impostare cancelsTouchesInView = false

Come questo:

let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    elsewhereTap.cancelsTouchesInView = false
    self.view.addGestureRecognizer(elsewhereTap)

2
override func viewDidLoad() {
        super.viewDidLoad()

self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))

}

func tap(sender: UITapGestureRecognizer){
        print("tapped")
        view.endEditing(true)
}

Prova questo, funziona


1

Quando nella vista è presente più di un campo di testo

Seguire le raccomandazioni di @ modocache per evitare di chiamareview.endEditing() , è possibile tenere traccia del campo di testo che è diventato il primo risponditore, ma che è disordinato e soggetto a errori.

Un'alternativa è chiamare resignFirstResponder() tutti i campi di testo nel viewcontroller . Ecco un esempio di creazione di una raccolta di tutti i campi di testo (che nel mio caso era comunque necessario per il codice di convalida):

@IBOutlet weak var firstName: UITextField!
@IBOutlet weak var lastName: UITextField!
@IBOutlet weak var email: UITextField!

var allTextFields: Array<UITextField>!  // Forced unwrapping so it must be initialized in viewDidLoad
override func viewDidLoad()
{
    super.viewDidLoad()
    self.allTextFields = [self.firstName, self.lastName, self.email]
}

Con la raccolta disponibile, è semplice iterare tutti:

private func dismissKeyboard()
{
    for textField in allTextFields
    {
        textField.resignFirstResponder()
    }
}

Quindi ora puoi chiamare il dismissKeyboard()tuo riconoscimento dei gesti (o ovunque sia appropriato per te). Lo svantaggio è che è necessario mantenere l'elenco di messaggi UITextFieldquando si aggiungono o rimuovono i campi.

Commenti benvenuti. Se c'è un problema con l'invito resignFirstResponder()a controlli che non sono il primo risponditore, o se esiste un modo semplice e garantito non corretto di rintracciare l'attuale primo risponditore, mi piacerebbe saperlo!

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.