Aller au contenu
MobileiOSSwiftUI

iOS 16, dessine moi une modale

Découvrez les avancées saisissantes de SwiftUI dans iOS 16.0 ! Avec un nouveau modifier, affichez des modales et passez facilement d'une taille à une autre selon vos préférences, offrant ainsi une expérience utilisateur plus personnalisée.

Photo by Ameen ALmayuf / Unsplash

iOS 16.0 a apporté son lot de nouveautés dans SwiftUI et notamment sur les modales (sheets). Dans les versions antérieures d'iOS, il était compliqué d'afficher une modale qui ne prend qu'une partie de l'écran. Un nouveau modifier a fait son apparition pour rendre la tâche plus aisée. Il va même plus loin, en proposant de spécifier plusieurs tailles qui seront disponibles pour l'utilisateur. Ce dernier pourra ainsi passer d'une taille à une autre en fonction de la quantité d'informations qu'il souhaite consulter.

Configuration de la hauteur d'une modale

Le modifier presentationDetents(_:selection:) est désormais disponible et doit être attaché à la vue qui sera présentée sous forme de modale. Il a en premier paramètre un tableau d'éléments de type PresentationDetent et qui permettront de définir une ou plusieurs tailles pour la modale.
PresentationDetent est une énumération dont les différents cas permettent d'atteindre le même objectif, celui de définir une taille.

Tailles simples

On va retrouver deux cas très simples, large et medium. Le premier permettra à une modale de prendre toute la hauteur de l'écran tandis que le second en prendra la moitié.

struct ContentView: View {
    @State private var modaleAffichee: Bool = false
    
    var body: some View {
        Button("Afficher la modale avec les cas large et medium") {
            modaleAffichee.toggle()
        }.sheet(isPresented: $modaleAffichee) {
            Text("Modale pouvant prendre plusieurs tailles avec les cas large et medium")
                .presentationDetents([.large, .medium])
        }
    }
}
Example des cas de PresentationDetent .large et .medium

Tailles customisables

Fraction et height

Ces deux tailles vont permettre de spécifier des tailles personnalisées en fonction soit d'un pourcentage de l'écran soit d'une taille fixée.
fraction prend en paramètre une valeur comprise entre 0 et 1 qui correspond au pourcentage de taille d'écran que prendra la modale. (75% pour l'exemple ci-dessous).
height prend en paramètre une hauteur bien précise. (100 pour l'exemple ci-dessous)

struct ContentView: View {
    @State private var modaleAffichee: Bool = false
    
    var body: some View {
        Button("Afficher la modale avec les cas customisables fraction et height") {
            modaleAffichee.toggle()
        }.sheet(isPresented: $modaleAffichee) {
            Text("Modale pouvant prendre plusieurs tailles avec les cas fraction et height")
                .presentationDetents([
                    .fraction(0.75),
                    .height(100)
                ])
        }
    }
}
Example des cas de PresentationDetent .fraction et .height

Il peut être intéressant de créer une extension de `PresentationDetents` pour y ajouter des tailles customisables qui seront alors utilisées comme des tailles simples.

extension PresentationDetent {
    static let small: PresentationDetent = .fraction(0.25)
}

Text("Texte")
    .presentationDetents([.small])
Extension de PresentationDetent pour créer des cas simples

Taille selon le context

Pour ce dernier il faudra définir un nouveau type qui implémente le protocol CustomPresentationDetent et sa méthode height(in:). Le point fort de ce cas se trouve dans le paramètre context de la méthode. Il permet d'avoir accès à toutes les valeurs d'environnement (EnvironmentValues) de SwiftUI.
On pourra, par exemple, avoir accès à la verticalSizeClass qui nous permettra pour un iPhone de définir si l'on est en paysage ou en portrait. À partir de là on pourra alors définir des tailles différentes, une partie de l'écran en portrait et tout l'écran en paysage. La hauteur de l'écran étant disponible avec la propriété maxDetentValue sur le contexte.

struct ContentView: View {
    @State private var modaleAffichee: Bool = false
    
    var body: some View {
        Button("Afficher la modale avec le cas custom") {
            modaleAffichee.toggle()
        }.sheet(isPresented: $modaleAffichee) {
            Text("Modale prenant une taille définie par le cas custom")
                .presentationDetents([
                    .custom(tailleCustomisee.self)
                ])
        }
    }
}

private struct tailleCustomisee: CustomPresentationDetent {
    static func height(in context: Context) -> CGFloat? {
        if context.verticalSizeClass == .regular {
            return context.maxDetentValue * 0.5
        } else {
            return context.maxDetentValue
        }
    }
}
Example du cas de PresentationDetent .custom

Présélection d'une taille spécifique.

Dans le cas où plusieurs tailles sont passées en paramètre, ce sera celle impliquant la plus petite hauteur qui sera utilisée en premier par le système pour afficher la modale. Il est cependant possible de spécifier celle que l'on souhaiterait voir utilisée en premier en spécifiant le paramètre selection de la méthode.
À noter que si la taille sélectionnée n'est pas présente dans la liste des tailles passées, un message sera affiché dans la console. "Cannot set selected sheet detent if it is not included in supported sheet detents"

0:00
/
Exemples des différents cas de PresentationDetent


Affichage de l'indicateur de redimensionnement

Second modifier a être disponible, presentationDragIndicator(_:) permet d'afficher ou non l'indicateur de redimension d'une modale.Par défaut une modale possède un petit indicateur horizontal positionné en haut de son contenu dans le cas où plusieurs tailles ont été défini. L'utilisateur est ainsi au courant que la modale est redimensionnable.
Il est donc possible de forcer l'affichage ou la disparition de l'indicateur en passant la valeur .visible ou .hidden.
À noter qu'il est recommandé, dans les guidelines Apple, d'afficher l'indicateur à partir du moment où la modale est redimensionnable. Cette recommendation est mise en place automatiquement avec la présence ou non de plusieurs tailles.

Affichage de l'indicateur de redimensionnement

Dernier