• 8 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/05/2023

Gérez le clavier

Si vous vous êtes amusé à jouer un peu avec votre formulaire, vous vous êtes sans doute aperçu que sans que vous ayez quoi que ce soit à 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...

Le clavier est apparu sur la page et masque 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.

Clavier numérique plutôt qu'Azerty sur l'interface d'inscription
Apparition du clavier numérique

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'affiche 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 cliquer 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 :

Bibliothèque des composants, avec l'objet Tap Gesture Recognizer

Et glissez-le sur la vue principale. Je vous suggère d'utiliser le panneau latéral gauche dans votre storyboard (Document Outline) pour être certain d'atterrir au bon endroit.

Un GIF montrant comment glisser-déposer le Tap Gesture Recognizer dans la vue principale.
Encore un drag !

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

Tap Gesture Recognizer pop-up
Tap Gesture Recognizer pop-up

Création de l'action

Nous allons maintenant pouvoir créer l'action correspondant à notre  Tap Gesture Recognizer  . Vous savez le 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'aie 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 !

Et la touche de retour ?

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

Un clavier d'iPhone avec le bouton continuer
Continuer = retour

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 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.

Gif avec demonstraction de l'action drag partant du champ Nom vers l'Outlet delegate
Drag partant du champ Nom vers l'Outlet 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    !

Et pour que le contrôleur l'adopte, il faut ajouter une extension à la classe, comme nous l’avons vu dans le chapitre précédent.

extension FormViewController: 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 doit être à 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.

Pour réaliser la deuxième solution, il va falloir effectuer les actions suivantes :

  1. Écouter les notifications d’affichage et de disparition du clavier.

  2. Déplacer toute la vue vers le haut ou vers le bas en fonction de la notification reçue.

Pour cela, rien de plus simple. iOS fournit deux notifications pour déterminer l’affichage et la disparition du clavier, que nous pouvons écouter via le  NotificationCenter  .

Commencer par créer deux méthodes pour capter les notifications :

@objc func keyboardAppear(_ notification: Notification) {

}

@objc func keyboardDisappear(_ notification: Notification) {

}

Puis demander au NotificationCenter d’utiliser ces deux fonctions en cas d’affichage ou de disparition du clavier :

NotificationCenter.default.addObserver(self, selector: #selector(keyboardAppear(_:)), name: UIViewController.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDisappear(_:)), name: UIViewController.keyboardWillHideNotification, object: nil)

Ensuite, dans la méthode  keyboardAppear  , nous allons faire en sorte de remonter notre vue pour que le bas de la vue soit toujours au-dessus du clavier :

@objc func keyboardAppear(_ notification: Notification) {
        guard let frame = notification.userInfo?[UIViewController.keyboardFrameEndUserInfoKey] as? NSValue else { return }
        let keyboardFrame = frame.cgRectValue
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardFrame.height
        }
    }

Puis faire l’inverse dans le cas de  keyboardDisappear  :

@objc func keyboardDisappear(_ notification: Notification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

Et voici le résultat :

Interface d'inscription avec tous les éléments
On y est presque !

Toutefois, comme vous pouvez le remarquer, tout ce qui est en haut de l’écran disparaît. Cette solution n’est pas toujours idéale.

Rassurez-vous, il en existe d'autres, comme l’utilisation de Scroll View, ou bien encore la possibilité de ne pas remonter complètement l’écran mais uniquement une partie. Toutefois je ne détaillerai pas toutes les solutions dans ce cours. Je vous invite à consulter les réponses sur ce Stack Overflow, il vous donnera quelques pistes de solutions. N'hésitez pas à faire vos propres recherches sur Internet, car les solutions évoluent aussi avec les mises à jour d’iOS.

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