NEW: Join my free 100 Days of SwiftUI challenge today! >>

Touches finales : hidesBarsOnTap, marges sur l'iPhone X

À ce stade, votre projet fonctionne parfaitement : vous pouvez appuyer sur Cmd + R pour l’exécuter, parcourir rapidement les images du tableau, puis appuyer sur l’une d'entre elles pour l’afficher. Mais avant de terminer ce projet, nous allons effectuer plusieurs autres petits changements qui rendent le résultat final un peu plus raffiné.

Tout d'abord, vous avez peut-être remarqué que toutes les images sont étirées pour remplir l'écran. Ce n'est pas un accident - c'est le paramètre par défaut de UIImageView.

Quelques clics suffisent pour résoudre ce problème : cliquez sur Main.storyboard, sélectionnez l'élément Image View dans Detail View controller, puis choisissez l'onglet Attributes Inspector dans le volet de droite - il s'agit du quatrième onglet, juste à gauche de l'icône de la règle.

Si vous n’avez pas envie de le chercher, appuyez simplement sur Cmd + Alt + 4 pour l’afficher. L'étirement est provoqué par le mode d'affichage, qui est un menu déroulant dont la valeur par défaut est "Scale to Fill" (remplissage à l'échelle). Changez-le en "Aspect Fit" (Ajuster le format) et ce premier problème est résolu.

Le mode d'affichage "Aspect Fit" pour les éléments UIImageView les oblige à redimensionner leurs images pour les rendre entièrement visibles.

Si vous vous posez la question, "Aspect Fit" redimensionne l'image pour qu'elle soit entièrement visible. Il y a aussi "Aspect Fill", qui redimensionne l'image de manière à ne pas laisser d'espace vide. Cela signifie généralement le rognage de la largeur ou de la hauteur. Si vous utilisez "Aspect Fill" (Remplir en conservant l’aspect), l’image déborde en dehors de la zone de visualisation. Veillez donc à cocher "Clip to Bounds" pour éviter ceci.

Le deuxième changement que nous allons effectuer consiste à permettre aux utilisateurs de visualiser les images en plein écran, sans aucune barre de navigation. Il existe un moyen vraiment très simple d'y parvenir, et il s'agit d'une propriété de UINavigationController appelée hidesBarsOnTap. Lorsque celle-ci est définie sur true, l'utilisateur peut appuyer n'importe où sur le contrôleur de vue actuel pour masquer la barre de navigation, puis appuyer de nouveau pour l'afficher.

Mise en garde : vous devez la configurer avec soin lorsque vous travaillez avec un iPhone. Si nous l'activons tout le temps, cela affectera également les taps sur la vue affichant le tableau, provoquant la pagaille lorsque l'utilisateur tente de sélectionner des éléments. Nous ne devons donc l'activer que lorsque Detail View Controller est affiché, puis la désactiver lorsqu'il est caché.

Vous avez déjà rencontré la méthode viewDidLoad(), appelée lorsque la mise en page du contrôleur de vue a été chargée. Il y en a plusieurs autres qui sont appelées lorsque la vue est sur le point d'être affichée, quand elle vient d'être affichée, quand elle va disparaître et quand elle a disparu. Celles-ci sont appelées respectivement viewWillAppear(), viewDidAppear(), viewWillDisappear() et viewDidDisappear(). Nous allons utiliser viewWillAppear() et viewWillDisappear() pour modifier la propriété hidesBarsOnTap afin qu'elle ne soit définie sur true que lorsque Detail View Controller est affiché.

Ouvrez DetailViewController.swift, puis ajoutez ces deux nouvelles méthodes directement à la suite de la méthode viewDidLoad() :

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationController?.hidesBarsOnTap = true
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.hidesBarsOnTap = false
}

Il y a quelques points importants à noter ici:

  • Nous utilisons le mot-clé override pour chacune de ces méthodes, car elles ont déjà des valeurs par défaut définies dans UIViewController et nous lui demandons d'utiliser les nôtres à la place. Ne vous inquiétez pas si vous ne savez pas quand utiliser ou non override, car si vous ne l'utilisez pas et que c'est obligatoire, Xcode vous le dira.
  • Les deux méthodes ont un seul paramètre : que l'action soit animée ou non. Nous ne nous en soucions pas vraiment dans ce cas, alors ignorons le.
  • Les deux méthodes utilisent à nouveau le préfixe super : super.viewWillAppear() et super.viewWillDisappear(). Cela signifie "indique à mon type de données parent que ces méthodes ont été appelées". Dans ce cas, cela signifie qu'il transmet la méthode à UIViewController, qui peut effectuer son propre traitement.
  • Nous utilisons à nouveau la propriété navigationController, ce qui fonctionnera bien car nous avons été placés sur la pile du contrôleur de navigation à partir de ViewController. Nous accédons à la propriété à l’aide du "?". Par conséquent, si nous ne sommes pas dans un contrôleur de navigation, les lignes hidesBarsOnTap ne feront rien.

Si vous exécutez l'application maintenant, vous verrez que vous pouvez appuyer sur le nom d'une image pour l'afficher à sa taille d'origine, et qu'elle ne sera plus étirée. Lorsque vous visualisez une image, vous pouvez appuyer n'importe où à l'écran pour masquer la barre de navigation en haut, puis taper pour l'afficher à nouveau.

Le troisième changement est minime mais important. Si vous regardez d'autres applications qui utilisent des Table Views et des Navigation Controllers pour afficher des écrans (encore une fois, l'application Réglages est idéale pour cela), vous remarquerez peut-être des flèches grises à droite des cellules du tableau. C’est un indice subtil de l’interface utilisateur indiquant que taper sur cette ligne affichera plus d’informations.

Il ne faut que quelques clics dans Interface Builder pour afficher cette flèche dans notre tableau. Ouvrez Main.storyboard, puis cliquez sur Table View Cell - c’est celle qui indique "Title", directement sous "Prototype Cells". Table View contient une cellule, la cellule contient une vue, et la vue contient un Label appelée "Title", il est donc facile de sélectionner le mauvais élément. Par conséquent, vous trouverez probablement plus facile d’utiliser le volet Document Outline pour sélectionner exactement l'élément désiré : vous souhaitez sélectionner le libellé "Picture", qui est l’identifiant (Identifer) que nous avons associé à la cellule de notre tableau.

Lorsque cet élément est sélectionnée, vous devriez pouvoir accéder à Attributes Inspector (l'inspecteur des propriétés) dans le volet de droite et voir "Style : Basic", "Identifier : Picture", etc. Vous verrez également "Accessory : None" - veuillez le remplacer par "Disclosure Indicator", ce qui entraînera l'affichage de la flèche grise.

Le quatrième est également un petit changement mais tout aussi important : nous allons placer du texte dans la barre grise en haut. Vous avez déjà vu que les contrôleurs de vue ont les propriétés storyboard et navigationController que nous obtenons depuis UIViewController. Eh bien, ils ont aussi une propriété title qui est automatiquement lue par le contrôleur de navigation : si vous fournissez ce titre, il sera affiché dans la barre de navigation grise en haut.

Dans ViewController, ajoutez ce code à viewDidLoad() après l'appel à super.viewDidLoad():

title = "Storm Viewer"

Ce titre est également utilisé automatiquement pour le bouton de retour "Back", afin que les utilisateurs sachent vers quoi ils retournent.

Dans DetailViewController, nous pourrions ajouter quelque chose comme ceci à viewDidLoad() :

title = "View Picture"

Cela fonctionnerait bien, mais au lieu de cela, nous allons utiliser du texte dynamique : nous allons plutôt afficher le nom de la photo sélectionnée.

Ajoutez ceci à la méthode viewDidLoad() dans le fichier DetailViewController.swift :

title = selectedImage

Nous n’avons pas besoin ici de déballer selectedImage parce que selectedImage et title sont de type optional strings (chaînes de caractères optionnelles). Nous affectons un type de donnée optional strings à un autre. title est optionnel car il est nil par défaut : les contrôleurs de vue qui n’ont pas de titre n’affichent aucun texte dans la barre de navigation.

Grands titres sous iOS 11

Il s’agit d’un changement tout à fait facultatif, mais j’ai voulu vous le présenter assez tôt afin que vous puissiez l’essayer et voir ce que vous en pensez.

iOS 11 a remanié les directives d’Apple pour le design dans de nombreux endroits, mais le plus visible est l’utilisation de gros titres - le texte qui apparaît dans la barre grise en haut des applications. Le style par défaut est un texte de petite taille, ce que nous avons eu jusqu’à présent, mais avec quelques lignes de code, nous pouvons adopter le nouveau design.

Tout d’abord, ajoutez ceci à viewDidLoad() dans ViewController.swift :

navigationController?.navigationBar.prefersLargeTitles = true

Cela active de gros titres dans toute notre application, et vous verrez une différence immédiate : "Storm Viewer" devient beaucoup plus grand et, dans Detail View Controller, tous les titres des images sont également de grande taille. Vous remarquerez que le titre n'est plus statique non plus - si vous tirez doucement vers le bas, vous verrez qu'il s'étire très légèrement et si vous essayez de faire défiler l'écran vers le haut, vous verrez les titres se rétrécir.

Apple recommande d'utiliser de gros titres uniquement lorsque cela vous semble judicieux, ce qui signifie généralement uniquement sur le premier écran de votre application. Comme vous l’avez vu, le comportement par défaut lorsqu’il est activé est d’avoir des gros titres partout, mais c’est parce que chaque nouveau contrôleur de vue inséré dans la pile du contrôleur de navigation hérite du style de son prédécesseur.

Dans cette application, nous voulons que "Storm Viewer" apparaisse en gros, mais que l'écran affichant l'image ait l'air normal. Pour y parvenir, nous devons ajouter une ligne de code à viewDidLoad() dans DetailViewController.swift:

navigationItem.largeTitleDisplayMode = .never

C’est tout ce dont vous avez besoin - les gros titres devraient maintenant se comporter correctement.

Et qu'en est-il de l'iPhone X?

L'iPhone X est le premier iPhone dont l'écran n’est pas rectangulaire, ce qui crée des problèmes intéressants. En particulier, les coins arrondis de l’écran peuvent facilement rogner du contenu s’il n’est pas positionné correctement. Le système essaie donc de s’adapter en créant des zones sécurisées, des parties de l’écran qui sont automatiquement ignorées pour éviter tout rognage.

Dans cette application, notre contrôleur de vue contenant le tableau s'exécute automatiquement d'un bord à l'autre, car Apple a fait tout le travail difficile pour nous, ce qui n'est pas le cas de l'image dans Detail View Controller - il y aura un espace blanc en bas pour laisser de la place à la barre d'accueil.

C’est parfois ce que vous voudrez, mais ici, cela ne semble plutôt pas satisfaisant. Heureusement, la solution est simple : ouvrez Main.storyboard, sélectionnez View dans Detail View Controller, puis décochez la case Safe Area Layout Guide dans Size Inspector (l’inspecteur des tailles), le cinquième onglet dans le volet de droite. Cela demandera à la vue (et à toutes ses sous-vues) d’être exécutée bord à bord, ce qui est mieux.

Tant que nous parlons de l’iPhone X et des autres appareils dotés de l'encoche, étendons notre utilisation de hidesBarsOnTap de sorte que la barre d’accueil soit également masquée. Ceci est contrôlé en outrepassant une propriété calculée appelée prefersHomeIndicatorAutoHidden - si elle retourne la valeur true, la barre d'accueil disparaîtra après quelques secondes pour ne réapparaître automatiquement que lorsque l'utilisateur touche à nouveau l'écran.

Nous allons écrire cette méthode pour qu’elle retourne la valeur de la propriété hidesBarsOnTap de notre contrôleur de navigation, ce qui signifie que les barres de navigation et d'accueil doivent disparaître ou réapparaître ensemble.

En théorie, nous devrions toujours avoir un contrôleur de navigation donc nous pourrions probablement déballer de force sa propriété. Cependant, une meilleure idée est de l’utiliser comme optionnel et de fournir false comme valeur par défaut si le contrôleur de navigation n’est pas présent. Ajoutez maintenant cette propriété à DetailViewController.swift :

override var prefersHomeIndicatorAutoHidden: Bool {
    return navigationController?.hidesBarsOnTap ?? false
}

Remarque : L'opérateur ?? est appelé l'opérateur nil coalescing, et dans ce cas, cela signifie "si le contrôleur de navigation n'existe pas, renvoie false plutôt que d'essayer de lire sa propriété hidesBarsOnTap."

Cette propriété est vérifiée lorsque le contrôleur de vue est affiché pour la première fois, mais elle sera également appelée à chaque fois que les barres seront masquées avec hidesBarsOnTap. Notre travail est donc terminé : la barre d'accueil devrait disparaître automatiquement quelques secondes après la disparition de la barre grise du haut de l'écran.

C’est le dernier des changements - nous avons terminé ! Allez-y et lancez le projet maintenant et admirez votre travail.

LEARN SWIFTUI FOR FREE I have a massive, free SwiftUI video collection on YouTube teaching you how to build complete apps with SwiftUI – check it out!

MASTER SWIFT NOW
Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!