• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 26/02/2020

Gérez le clavier

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Si vous vous êtes amusés à jouer un peu avec votre formulaire, vous vous êtes sans doute aperçu que sans que vous n'ayez rien à faire, votre clavier apparaît automatiquement lorsque vous cliquez sur un champ de texte.

C'est pratique, mais du coup ça prend une bonne partie de l'écran et on ne peut plus cliquer sur le bouton Valider...

Dans ce chapitre, nous allons apprendre à gérer la disparition du clavier !

Rappel sur le champ de texte

Tant qu'on en est à parler du clavier, laissez-moi vous faire un petit rappel sur ce qu'on a vu avec le champ de texte.

Le clavier est entièrement lié au champ de texte.

Par exemple, c'est le champ de texte qui décide du type de clavier qui s'affiche. On a ensemble modifié la propriété Keyboard Type pour que le champ de texte Téléphone affiche plutôt le clavier suivant.

Cela veut dire que c'est également le champ de texte qui décide de l'apparition et de la disparition du clavier.

Clavier dans le simulateur

Si vous lancez l'application dans le simulateur, le clavier ne s'affichera peut-être pas. Cela est dû à un réglage spécial du simulateur. Quand vous interagissez avec une application dans le simulateur, vous avez l'option d'utiliser le clavier iOS présent sur l'écran du simulateur ou d'utiliser le clavier de votre Mac.

Vous pouvez alterner entre les deux options en allant dans Hardware > Keyboard > Connect Hardware Keyboard. Vous pouvez également utiliser le raccourci shift + cmd + K.

Une tape et... disparition !

Le clavier apparaît donc automatiquement, mais il ne disparaît pas ! Le réflexe commun, c'est de taper n'importe où en dehors du champ de texte pour faire disparaître le clavier. Alors, essayons de rajouter cette fonctionnalité à notre page !

Ajout du Tap Gesture Recognizer

Pour y parvenir, il faut associer le geste "Tap" à "n'importe où sur la page". Et vous savez déjà faire cela ! Nous allons utiliser UITapGestureRecognizer et nous allons le relier à la vue principale du FormViewController.

Sélectionnez Tap Gesture Recognizer dans la bibliothèque des objets :

Et glissez-le sur la vue principale. Je vous suggère d'utiliser le panneau de droite (Document Outline) pour être certain d'atterrir au bon endroit.

Le Tap Gesture Recognizer est maintenant ajouté et relié à la vue principale.

Création de l'action

Nous allons maintenant pouvoir créer l'action correspondant à notre Tap Gesture Recognizer. Vous savez faire, il suffit de faire un control-drag depuis le Tap Gesture Recognizer vers le code. Vous pouvez nommer l'action dismissKeyboard.

Le code suivant est généré :

@IBAction func dismissKeyboard(_ sender: UITapGestureRecognizer) {
}

Dans cette méthode, nous allons rédiger le code permettant de cacher le clavier.

À vos outlets

On l'a dit, c'est la responsabilité du champ de texte de cacher le clavier. Donc nous allons avoir besoin d'accéder aux champs de texte dans le code. Pour cela, créez deux outlets correspondant aux deux champs de texte.

Voici mon résultat :

@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var phoneTextField: UITextField!

La notion de firstResponder

Tout est prêt ! Nous avons le geste, l'action et les outlets. Il ne reste plus qu'à rédiger la commande. Et cette commande, elle ressemble à ceci :

nameTextField.resignFirstResponder()

Pourquoi ça ne s'appelle pas nameTextField.hideKeyboard()? C'est quoi un responder?

Très bonnes questions ! En iOS, un responder (répondeur en français) est un objet qui peut répondre à des évènements et les gérer. En gros, toutes les vues sont des répondeurs, car elles peuvent toutes au moins gérer des gestes sur l'écran tactile.

Le premier répondeur (firstResponder) est l'objet qui est en train d'être utilisé. Il ne peut y en avoir qu'un seul. Par exemple, lorsqu'on tape du texte dans un champ de texte, il n'y a qu'un seul champ de texte qui répond. On ne peut pas taper du texte sur plusieurs champs en même temps.

Autre exemple, mettons que j'ai deux boutons l'un en dessous de l'autre et que j'appuie dessus. Techniquement, les deux boutons ont été touchés. Mais un seul lancera son action, on l'appelle le firstResponder.

Lorsque l'on touche le champ de texte, il devient firstResponder. Et lorsqu'un champ de texte devient firstResponder, il affiche le clavier. N'importe quelle vue peut devenir le firstResponder en appelant la méthode :

nameTextField.becomeFirstResponder()

À l'inverse, n'importe quelle vue peut décider de ne plus être le firstResponder et pour cela, elle utilise la méthode qu'on a vue au-dessus :

nameTextField.resignFirstResponder()

Lorsqu'un champ de texte n'est plus firstResponder, cela veut dire que l'utilisateur n'est plus en train d'interagir avec lui et que du coup le clavier n'a plus de raison d'être présenté. Il disparaît.

Vous pouvez faire la même chose avec phoneTextField et votre action devient :

@IBAction func dismissKeyboard(_ sender: UITapGestureRecognizer) {
nameTextField.resignFirstResponder()
phoneTextField.resignFirstResponder()
}

Vous pouvez tester dans le simulateur et ça marche !

Je résume :

  • On a créé un geste (Tap) que l'on a associé à la vue principale pour qu'il soit disponible n'importe où sur la page.

  • On a associé une action au geste.

  • Dans l'action, on appelle la méthode resignFirstResponder sur les deux champs de texte pour que le clavier disparaisse.

Et la touche de retour ?

La touche de retour sur le clavier, c'est celle-ci :

Lorsqu'on appuie sur cette touche, l'utilisateur peut vraisemblablement s'attendre à ce que le clavier disparaisse. Et pour cela, il faut que la vue puisse prévenir le contrôleur de l'évènement "a appuyé sur la touche retour". Si seulement elle pouvait lui déléguer la....

On va utiliser un delegate !

Mais quelle vivacité d'esprit ! Je suis ébahi. Je vous adore !

En effet, on va utiliser un delegate. Et on suit toujours les mêmes étapes :

  1. Le champ de texte va nommer le contrôleur comme son delegate.

  2. Le contrôleur s'engage à répondre aux questions du champ de texte en adoptant le protocole correspondant.

  3. Le contrôleur répond aux questions en se conformant au protocole et donc en implémentant les méthodes de ce dernier.

1. Le champ de texte nomme le contrôleur comme son delegate

Pour cela, vous vous souvenez, on utilise un control-drag depuis le champ de texte vers le contrôleur et dans la pop-up, on clique sur delegate.

Vous pouvez répéter l'opération pour le deuxième champ de texte.

2. Le contrôleur adopte le protocole

Le protocole correspondant s'appelle UITextFieldDelegate. Oui... ils ne font pas dans la créativité. En même temps, heureusement :D !

Et pour que le contrôleur l'adopte, il faut l'ajouter à la déclaration de la classe comme on l'a vu au chapitre précédent.

class FormViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {
}

3. Le contrôleur se conforme au protocole

Il ne nous reste maintenant plus qu'à implémenter la méthode qui nous intéresse dans ce protocole et qui correspond à l'évènement "a appuyé sur la touche retour". Cet évènement s'appelle :

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

Cette fonction prend en paramètre un textField. C'est le champ de texte qui vient de subir l'évènement "a appuyé sur la touche retour". Et elle renvoie un booléen qui est à true si vous souhaitez que la méthode suive son implémentation normale, ce qui sera presque toujours le cas.

Mais avant de renvoyer le booléen, on peut faire ce qu'on veut et notamment :

textField.resignFirstResponder()

Et maintenant le champ de texte disparaîtra lorsqu'on appuiera sur la touche de retour !

Voici le code complet de la fonction :

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

Allez plus loin

Un dernier cas courant que vous rencontrerez en manipulant les claviers, c'est celui d'un clavier qui recouvre un champ de texte. C'est notamment le cas si vos champs de texte sont situés en bas de l'écran.

Dans ce cas, l'utilisateur ne voit pas ce qu'il écrit !

Il y a deux solutions :

  1. Ne pas mettre de champ de texte en bas. C'est évident, mais je le précise parce que ça vaut parfois le coup de modifier le design de son application dans ce but.

  2. Faire glisser la vue principale vers le haut pour que le champ de texte soit plus haut que le clavier. Dans ce cas, c'est bien toute la vue principale qui glisse vers le haut, pour ne pas altérer le design.

Je ne détaillerai pas cette deuxième option, mais il faut que le contrôleur écoute les notifications d'apparition et disparition du clavier et ensuite, on fait une translation de la vue principale vers le haut en calculant bien la distance nécessaire.

Je vous invite à jeter un œil à ce tutoriel si vous rencontrez le problème. Vous pouvez aussi compléter avec cette réponse Stack Overflow qui est moins détaillée, mais régulièrement mise à jour.

En résumé

  • Le champ de texte est l'objet qui gère le clavier.

  • On peut utiliser un Tap Gesture Recognizer associé à la vue principale pour faire disparaître le clavier après l'appui sur n'importe quel écran.

  • Lorsque le champ de texte devient firstResponder, le clavier apparaît. Lorsque le champ de texte ne l'est plus, le clavier disparaît. Deux méthodes sont associées à ces évènements :

textField.becomeFirstResponder()
textField.resignFirstResponder()
  • Pour que le clavier disparaisse à l'appui sur la touche de retour, on utilise le UITextFieldDelegate et en particulier la méthode textFieldShouldReturn.

Dans le prochain chapitre, nous allons apprendre à récupérer les données de notre formulaire !

Exemple de certificat de réussite
Exemple de certificat de réussite