Mise en page Flexbox
Disposer les éléments avec Flexbox, éviter les barres du téléphone avec SafeAreaView et faire défiler un contenu trop long avec ScrollView.
Objectifs de la séance
- comprendre les deux axes de Flexbox (
flexDirection,justifyContent,alignItems) ; - espacer les éléments avec
gap; - limiter la largeur du contenu sur grand écran avec
maxWidthetalignSelf; - protéger le contenu des barres du téléphone avec
SafeAreaView; - faire défiler l'écran avec
ScrollViewetcontentContainerStyle.
Petite vérification
Avant de commencer, vérifiez si vous savez...
- lancer l'application dans le navigateur et compter les boutons de réponse affichés
- dans
src/app/index.tsx, citer l'attribut que doit porter chaque<BoutonReponse>généré parmap - ouvrir la console du navigateur (
F12) et vérifier qu'aucun avertissement au sujet des clés (« unique key ») n'apparaît
📌 Réponse attendue
Notions théoriques
Flexbox : deux axes
En React Native, tout composant View organise ses enfants avec Flexbox. L'idée : un conteneur
dispose ses enfants le long d'un axe principal, et les aligne sur l'axe secondaire
(perpendiculaire).
| Propriété | Rôle |
|---|---|
flexDirection | direction de l'axe principal : "column" (de haut en bas, valeur par défaut) ou "row" (de gauche à droite) |
justifyContent | répartition le long de l'axe principal |
alignItems | alignement sur l'axe secondaire |
gap | espace entre deux enfants consécutifs |
flexWrap | "wrap" : les enfants passent à la ligne quand la place manque |
flex: 1 | l'élément occupe tout l'espace disponible |
Sur le Web, flex-direction vaut row par défaut. En React Native, la valeur par défaut est
column : les enfants d'une View s'empilent donc verticalement sans rien écrire.
Valeurs courantes de justifyContent (avec flexDirection: "row", trois enfants A, B, C) :
| Valeur | Résultat |
|---|---|
"flex-start" (défaut) | [A][B][C] |
"center" | [A][B][C] |
"flex-end" | [A][B][C] |
"space-between" | [A] [B] [C] |
alignItems accepte "flex-start", "center", "flex-end" et "stretch" (valeur par défaut :
les enfants s'étirent sur toute la largeur de l'axe secondaire).
gap : l'espace entre les éléments
Au lieu d'ajouter un marginBottom à chaque enfant, on règle l'écart une seule fois sur le parent
avec gap :
contenu: { gap: 16 }, // 16 d'écart entre chaque enfant du conteneur
Le code est plus court, et un nouvel élément inséré ne casse pas les marges.
Largeur maximale et centrage
Sur un grand écran (navigateur, tablette), un contenu qui s'étire sur toute la largeur devient
illisible. On limite sa largeur avec maxWidth, et on le centre avec alignSelf: "center" :
contenu: { width: "100%", maxWidth: 600, alignSelf: "center" }
width: "100%" signifie « toute la largeur disponible », maxWidth: 600 « mais jamais plus de 600 ».
Sur un téléphone étroit, le contenu occupe tout l'écran ; sur un grand écran, il reste centré.
SafeAreaView : respecter les zones réservées
Un téléphone possède des zones que l'application ne doit pas recouvrir : l'encoche (notch), la barre
d'état, la barre de navigation du bas ou l'indicateur de retour à l'accueil. Le composant
SafeAreaView ajoute automatiquement une marge intérieure égale à ces zones.
import { SafeAreaView } from "react-native-safe-area-context";
<SafeAreaView style={styles.ecran} edges={["bottom"]}> ... </SafeAreaView>
- on l'importe depuis
react-native-safe-area-context(bibliothèque déjà installée par le modèle) ; edgesindique quels bords protéger : ici seulement"bottom", car la barre de titre de la pile d'écrans (Stack) gère déjà le haut de l'écran.
Sans SafeAreaView, le dernier bouton de la liste peut se retrouver sous la barre du bas d'un
téléphone : il est affiché mais impossible à toucher. Ce défaut n'apparaît pas dans le navigateur d'un
ordinateur, d'où l'importance de tester aussi sur un vrai appareil.
ScrollView : faire défiler un contenu
Si le contenu dépasse la hauteur de l'écran (une question longue, un petit téléphone), il est coupé.
ScrollView ajoute le défilement. Elle possède deux propriétés de style :
| Propriété | S'applique à |
|---|---|
style | le cadre de la ScrollView elle-même |
contentContainerStyle | le contenu qui défile (marges, gap, largeur maximale...) |
Les marges et la mise en page du contenu se règlent donc dans contentContainerStyle. (Pour de très
longues listes, on utilisera plus tard FlatList, qui n'affiche que les éléments visibles.)
TP pour réfléchir et résoudre des problèmes
Vous allez améliorer la mise en page de l'écran d'accueil : titre et badge de niveau sur une ligne,
espacement régulier, contenu protégé des barres du téléphone, défilement et largeur limitée. Vous êtes
toujours sur la branche feature/composants.
Étape 1 — Ajouter un badge de niveau
Dans src/app/index.tsx, importez ScrollView et SafeAreaView (vous les utiliserez plus loin) :
import { ScrollView, StyleSheet, Text, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
Entourez ensuite le titre d'une View appelée entete et ajoutez à côté un badge qui affiche le niveau de
la question :
Pour placer deux éléments côte à côte, on les regroupe dans une View dédiée : c'est ce conteneur qui reçoit
les règles Flexbox, pas les éléments eux-mêmes.
Étape 2 — Disposer le titre et le badge sur une ligne
Par défaut, les enfants de entete s'empilent (axe column). Dans StyleSheet, ajoutez le style entete :
complétez la ligne qui les place côte à côte :
Retenez la règle : justifyContent agit sur l'axe de la direction choisie, alignItems sur l'axe
perpendiculaire. En row, justifyContent répartit horizontalement et alignItems aligne verticalement.