> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# iOS 16, dessine moi une modale
- URL: https://www.sfeir.dev/mobile/ios-16-dessine-moi-une-modale/
- Published: 2022-09-30T13:28:00.000Z
- Updated: 2023-05-23T18:12:45.000Z
- Description: 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.
- Author: Arnaud Le Bourblanc
- Tags: Mobile, iOS, SwiftUI

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

```swift
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)

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

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

```swift
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

/

1×

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.

![](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2023/05/DragIndicator.png)

Affichage de l'indicateur de redimensionnement