Retour aux articles
AppleDesignProjets

iPhone Duo : repenser ses layouts SwiftUI, une grenouille à la fois 🐸

Trois dendrobates, un iPhone qui se plie, et une fiche qui garde ses repères : apprivoiser ArrangementView en SwiftUI.

Clément Sauvage14 min de lecture
iPhone Duo : repenser ses layouts SwiftUI, une grenouille à la fois 🐸

Construire un atlas de dendrobates avec SwiftUI pour comprendre ArrangementView sur iPhone Duo : split, overlay, état partagé et captures réelles du simulateur.

Un téléphone qui se plie, c’est une surface d’affichage en plus. Et quelques certitudes en moins. Les grenouilles, elles, plient leurs pattes sans ouvrir la documentation SwiftUI. On va essayer de s’en inspirer.

Jusqu’ici, on pouvait souvent résumer un layout adaptatif à une question : « combien de place ai-je ? » Avec l’iPhone Duo, il faut aussi se demander où cette place se trouve. Une grande surface à plat, deux régions séparées par une pliure, un écran extérieur plus compact : les mêmes pixels ne rendent pas les mêmes services.

Apple introduit avec iOS 27.1 un conteneur SwiftUI pour organiser deux contenus liés : ArrangementView. Pour comprendre ce que ça change, j’ai construit FrogAtlas, un petit atlas de dendrobates. Des fiches, des photographies et une carte. Et des grenouilles suffisamment colorées pour nous changer des rectangles bleus des exemples de layout. 🐸

J’ai donné à l’application l’allure d’une ancienne encyclopédie naturaliste : papier ivoire, caractères à empattements, filets fins et planches légendées. Un croquis de D. tinctorius, généré par IA d’après une photographie créditée, accompagne les images de référence. Le bouton « Voir la photographie » permet de revenir à l’image source. Ambiance : vieux tome d’histoire naturelle, mais le sommaire répond au doigt.

Les captures de cet article viennent de cette application, exécutée dans le simulateur iPhone Duo sous iOS 27.1. Elles montrent le rendu logiciel, pas un test d’ergonomie sur un appareil physique. Les cadres officiels d’Apple permettent de distinguer l’écran extérieur, l’écran intérieur à plat et la position livre. Quelques pensionnaires du terrarium se sont aussi invités dans les marges.

Bienvenue dans le terrarium

FrogAtlas présente trois espèces : Dendrobates tinctorius, Dendrobates auratus et Dendrobates leucomelas. Une sélection pour la démonstration, pas un inventaire complet du genre. Trois espèces, trois robes, et aucun avis sur mes choix typographiques.

Les données viennent de la page Wikipédia consacrée aux Dendrobates et des fiches des espèces. Ce sont des amphibiens de la famille des Dendrobatidae, associés aux forêts tropicales humides d’Amérique centrale et du Sud. Le genre nous donne le contexte ; les fiches précisent les tailles, l’habitat et la répartition de chaque espèce.

Un petit détour par la taxonomie s’impose. La page du genre mélange encore « cinq espèces » et une liste qui comprend D. azureus. Le référentiel Amphibian Species of the World classe ce nom dans la synonymie de D. tinctorius. Dans l’application, la forme bleue « azureus » reste donc rattachée à cette espèce. Une couleur spectaculaire ne crée pas, à elle seule, une nouvelle espèce. Même un très beau bleu.

Côté interface, le besoin est simple. Je sélectionne une grenouille, je lis sa fiche, je regarde sa photographie. Puis je passe à la carte pour situer les régions où l’espèce est présente.

À plat, fiche et photographie peuvent cohabiter. En configuration livre, la pliure impose une séparation. Sur l’écran extérieur, je veux surtout conserver une fiche lisible et un moyen de changer d’espèce. Construire chaque écran séparément serait assez facile. Maintenir leur cohérence pendant les transitions l’est déjà moins.

FrogAtlas déplié : la fiche de Dendrobates tinctorius et sa planche illustrée occupent deux régions distinctes.

FrogAtlas, style split sur l’écran intérieur à plat. Planche artistique générée par IA d’après la photographie d’Olaf Leillinger, CC BY-SA 3.0. La photographie originale reste accessible dans l’application. Crédits complets en fin d’article.

Deux contenus liés, une responsabilité de layout

ArrangementView reçoit une vue primaire et une vue secondaire. Le style décrit leur relation spatiale. Le conteneur prend ensuite les décisions de disposition selon le contexte : proportions disponibles, classes de taille et régions réservées, dont la pliure.

Commençons par la fiche et la photographie :

enum AppLanguage {
    case french
    case english
}

NavigationStack {
    ArrangementView {
        FrogInformationView(frog: frog, language: .french)
    } secondary: {
        FrogPhotographyView(frog: frog, language: .french)
    }
    .arrangementViewStyle(.split)
}

L’enum AppLanguage appartient à notre application. Le paramètre language indique directement la langue choisie : .french ou .english.

Les noms FrogInformationView et FrogPhotographyView désignent les composants de notre application. Le conteneur et le style, eux, viennent de SwiftUI. Les extraits de cet article ciblent iOS 27.1 ; une application qui prend en charge des versions antérieures doit prévoir une alternative derrière un test de disponibilité.

Le style .split partage l’espace entre les deux vues. Dans le cas simple présenté par Apple, un conteneur plus large que haut favorise un partage horizontal ; un conteneur plus haut que large favorise un partage vertical. Réduire cette règle à « grand écran contre petit écran » ferait perdre une partie du sujet.

Ce qui m’intéresse ici, c’est la responsabilité que l’on déplace. La fiche décrit ses informations. La photographie présente son image. Le conteneur décide comment elles cohabitent. Je n’ai plus à répéter cette décision dans chaque composant.

La navigation garde son travail

Le nom peut prêter à confusion, mais ArrangementView ne fournit pas de navigation. Le catalogue, les destinations et le retour à l’écran précédent restent du ressort des conteneurs habituels.

Dans l’exemple, NavigationStack entoure l’arrangement. J’évite d’empiler un NavigationSplitView ou un TabView à l’intérieur pour lui faire jouer un rôle qui n’est pas le sien. J’évite aussi de placer l’arrangement dans un grand ScrollView qui engloberait toute la page. En revanche, la fiche peut avoir son propre défilement dans la région qui lui est attribuée.

La session Apple sur les layouts adaptatifs explique bien cette distinction entre navigation, disposition et contenu.

Partager le terrarium : le ratio de layout

Une moitié pour la fiche, une moitié pour l’image : c’est un point de départ, pas une obligation. Ici, la fiche contient du texte et bénéficie d’un peu plus de place. Le nom Dendrobates tinctorius n’est pas exactement taillé pour une colonne de trois caractères.

ArrangementView {
    VStack(spacing: 0) {
        FrogInformationView(frog: frog, language: .french)
    }
    .splitArrangementLayoutRatio(0.60)
} secondary: {
    FrogPhotographyView(frog: frog, language: .french)
}
.arrangementViewStyle(.split)

Le détail qui compte : le modificateur s’applique à l’enfant dont on exprime la préférence, pas à l’ensemble de l’ArrangementView. C’est aussi la forme montrée dans la documentation de splitArrangementLayoutRatio.

On demande ici environ 60 % de l’espace pour la fiche. Le ratio concerne l’axe de partage retenu. Il ne promet pas 60 % de l’écran dans toutes les positions : contraintes de layout, priorités et séparation physique restent à prendre en compte.

La petite VStack à un enfant sert de racine de région dans la démo. Le composant qui lit le contexte d’arrangement se trouve ainsi en dessous. Ce détail a son intérêt pratique : il faut vérifier le comportement réel des valeurs d’environnement, pas seulement constater que le code compile.

Adapter la fiche à ce que le conteneur a décidé

Une fiche large peut afficher les mesures dans deux blocs distincts. Une région plus compacte appelle une présentation plus courte. Les informations restent disponibles ; leur mise en forme change.

struct FrogInformationView: View {
    @Environment(\.splitArrangementAxis)
    private var arrangementAxis

    let frog: Frog
    let language: AppLanguage

    var body: some View {
        ScrollView {
            VStack(alignment: .leading) {
                Text(frog.scientificName)
                    .italic()

                if arrangementAxis == .horizontal {
                    FrogCharacteristicsGrid(frog: frog)
                } else {
                    FrogCharacteristicsSummary(frog: frog)
                }
            }
        }
    }
}

FrogCharacteristicsGrid et FrogCharacteristicsSummary représentent ici deux variantes de présentation. L’important est la question posée au système : quel axe l’arrangement utilise-t-il ?

splitArrangementAxis est optionnel. Hors d’un arrangement split, sa valeur peut être nil. Dans cet exemple, la présentation condensée sert aussi de repli raisonnable dans ce cas.

Je n’ai pas besoin de demander le modèle de l’iPhone ni de disperser des seuils de largeur dans le code. Cela ne supprime pas tous les besoins de mesure. Cela évite de mesurer à nouveau ce que le conteneur vient déjà de décider.

Petit écran : la grenouille sort du cadre

Sur une surface étroite, je peux préférer conserver seulement la fiche. Le style permet de limiter les axes :

ArrangementView {
    FrogInformationView(frog: frog, language: .french)
} secondary: {
    FrogPhotographyView(frog: frog, language: .french)
}
.arrangementViewStyle(.split.axes(.horizontal))

Si le conteneur ne peut pas partager l’espace suivant l’axe autorisé, la vue primaire reste seule. C’est une décision fonctionnelle autant qu’une décision graphique.

La photographie complète la fiche. Le sélecteur d’espèces, lui, permet de continuer à explorer l’application. Je le garde donc en dehors du contenu secondaire susceptible de disparaître.

FrogAtlas sur l’écran extérieur : la fiche reste visible quand le partage est limité à l’axe horizontal.

Écran extérieur, partage horizontal uniquement. La grande planche s’efface ; la fiche et la sélection d’espèces restent accessibles.

Il y a une nuance propre à notre exemple. La photographie peut disparaître pour lire une description textuelle. Dans une application d’identification visuelle sur le terrain, elle pourrait devenir indispensable. « Secondaire » décrit une priorité dans une tâche, pas une catégorie définitive de contenu.

La carte au fond, la grenouille au premier plan

Passons à l’atlas. Cette fois, je veux explorer une carte avec une petite fiche au premier plan. Le style .overlay correspond à cette relation.

ArrangementView {
    VStack(spacing: 0) {
        FrogSelectionPanel(frog: selectedFrog, language: .french)
    }
} secondary: {
    FrogWorldMap(selectedID: $selectedID, language: .french)
}
.arrangementViewStyle(.overlay)

Dans ce style, la vue primaire est au premier plan. La carte est la vue secondaire, même si elle occupe visuellement la plus grande surface. Primaire ne veut donc pas dire « la plus grande ».

FrogAtlas à plat : une fiche compacte est superposée à la carte interactive.

Style overlay à plat. La carte fournit le contexte géographique ; la fiche rappelle l’espèce sélectionnée. Fond cartographique : Apple Maps.

Quand l’appareil se replie, le conteneur peut séparer ces deux contenus en régions distinctes. C’est là que conserver exactement la même petite fiche laisserait beaucoup d’espace inutilisé.

La fiche déplie ses pattes, la sélection reste

Le composant peut lire sa position dans l’arrangement avec overlayArrangementZIndex :

struct FrogSelectionPanel: View {
    @Environment(\.overlayArrangementZIndex)
    private var zIndex

    let frog: Frog
    let language: AppLanguage

    var body: some View {
        if zIndex > 0 {
            CompactFrogCard(frog: frog)
        } else {
            FrogInformationView(frog: frog, language: language)
        }
    }
}

CompactFrogCard désigne la carte résumée de notre application. Superposée, elle laisse de la place au fond cartographique. Séparée, la fiche peut utiliser toute sa région et proposer le détail.

FrogAtlas partiellement replié : la carte et la fiche détaillée occupent chacune une région de l’écran.

Configuration livre dans le simulateur. La fiche gagne de la place sans changer d’espèce. La séparation centrale vient de la configuration de l’appareil.

Le point architectural est ailleurs : l’état de sélection appartient au parent, au-dessus des variantes de présentation. Dans FrogAtlas, un identifiant stable désigne l’espèce ; @AppStorage le conserve aussi entre deux lancements. Le téléphone se replie ; tinctorius reste tinctorius. Toute métamorphose en auratus à ce stade mérite un ticket de bug.

Même vigilance pour la carte : reconstruire son état à chaque changement de disposition peut perdre le cadrage choisi. Une transition réussie conserve le travail en cours. Elle ne se contente pas de produire une jolie capture avant et après.

En position posée sur une table, une séparation verticale peut aussi donner un rôle différent aux deux régions. Le contenu à consulter et les commandes à toucher n’ont pas forcément les mêmes besoins. C’est à valider en situation, notamment pour l’accessibilité et la portée des gestes.

Limiter l’overlay, avec une raison

Comme pour le split, on peut limiter les axes autorisés :

.arrangementViewStyle(.overlay.axes(.vertical))

Cette configuration restreint les possibilités de séparation. Je ne l’utiliserais pas simplement pour obtenir la même composition partout. Un bouton qui reste au même endroit mais devient difficile à atteindre près de la pliure n’a pas gagné grand-chose.

Le bon critère reste l’action de la personne. Peut-elle lire, comparer, sélectionner et revenir en arrière dans chaque position ? Si la séparation améliore cela, je préfère laisser le conteneur l’effectuer.

Un atlas ne doit pas inventer de précision

Le modèle garde les informations scientifiques indépendantes du layout :

struct Frog: Identifiable {
    let id: String
    let scientificName: String
    let family: String
    let habitat: String
    let distribution: String
    let sourceURL: URL
}

C’est un modèle simplifié pour l’article. L’application ajoute les traductions, les mesures, les crédits photographiques et les coordonnées de ses repères pédagogiques.

Les points sur la carte ne sont pas des observations, ni des contours d’aires de répartition. Ils servent à situer de grandes régions. L’interface le dit explicitement. Le point « tinctorius » n’est donc pas l’adresse postale d’une grenouille. Une localisation ponctuelle, une présence signalée dans un pays et une aire cartographiée sont trois niveaux d’information différents.

Pour un véritable atlas scientifique, il faudrait des données géographiques documentées, avec leur provenance, leur date et leur incertitude. Dessiner un polygone autour de quelques pays ne résoudrait pas le problème : cela donnerait seulement une forme plus convaincante à une approximation.

Je reste également prudent sur les chiffres biologiques. Une plage de taille dépend du sexe, des populations et des mesures disponibles. Un statut de conservation demande sa source et sa date. Pour cette démo de layout, je préfère quelques informations vérifiables à une fiche remplie de chiffres décoratifs.

Ce que je vérifierais avant de livrer

La compilation vérifie les types. Elle ne vérifie ni la lisibilité ni la continuité de l’expérience. Un build vert ne signifie pas que toutes les grenouilles sont bien installées. La démo a été compilée avec le SDK iOS 27.1 et les captures ont été réalisées en changeant réellement la position du simulateur.

Pour aller vers une application distribuée, ma liste de contrôle serait courte mais exigeante :

  • retrouver l’espèce sélectionnée après chaque ouverture, fermeture et rotation ;
  • conserver un accès aux fonctions essentielles quand la vue secondaire disparaît ;
  • tester les textes français et anglais avec de grandes tailles de caractères ;
  • vérifier le défilement, VoiceOver et les contrôles proches de la pliure ;
  • tester les transitions sur l’appareil, avec une personne qui tient réellement le téléphone.

J’ajouterais un dernier point : ne pas tout transformer parce qu’une API le permet. Un article qui défile peut déjà très bien fonctionner. Déplacer ses paragraphes entre deux régions risquerait surtout de faire perdre le fil.

Ce que je retiens d’ArrangementView

Je ne vois pas dans ce conteneur la fin du travail de design. Je vois une manière plus propre d’en exprimer une partie.

Les données décrivent les grenouilles. Les composants savent présenter une fiche, une photographie ou une carte. L’arrangement organise leur relation dans l’espace disponible. Et l’état garde la trace de ce que la personne est en train de faire.

Cette séparation est utile sur un téléphone pliable. Elle l’est aussi chaque fois qu’une interface doit vivre dans plusieurs formats sans devenir une collection d’écrans indépendants.

On écrit un peu moins de code pour placer les choses. On garde toute la responsabilité de choisir ce qui compte.

Les grenouilles peuvent continuer à sauter. La sélection, elle, reste à sa place. 🐸


Sources et crédits

Documentation consultée le 26 octobre 2026 : ArrangementView, ratio de layout, axe du split, Z-index de l’overlay, session Apple et Designing for iPhone Duo.

Données naturalistes, reformulées à partir de Wikipédia : Dendrobates, D. tinctorius, D. auratus, D. leucomelas. Textes des contributeurs sous CC BY-SA 4.0. Synonymie d’azureus vérifiée dans Amphibian Species of the World, AMNH.

Photographies Wikimedia Commons : D. tinctorius — Olaf Leillinger, D. auratus — Wildfeuer, D. leucomelas — Boucaque. Toutes trois sous CC BY-SA 3.0, redimensionnées et recadrées dans l’interface ; ces adaptations photographiques conservent cette licence. Le croquis de D. tinctorius est une interprétation artistique générée par IA d’après la photographie d’Olaf Leillinger, fournie sous la même licence. Captures : FrogAtlas, simulateur iPhone Duo ; cartographie : Apple Maps, attributions conservées.

Le croquis de D. auratus dans les marges est une interprétation artistique générée par IA d’après la photographie de Wildfeuer citée ci-dessus, sous CC BY-SA 3.0. Ces croquis servent à illustrer l’article, pas à identifier les espèces. Les cadres d’iPhone Duo proviennent des Apple Design Resources ; ils relèvent de la licence Apple Design Resources, distincte des licences des photographies et des croquis.


Comme tous les articles de ce blog, celui-ci part d’un texte écrit à la main, puis relu par une IA. La version anglaise a été réalisée avec l’aide d’une IA. Le code de FrogAtlas a été partiellement développé avec un agent IA. Les captures d’écran ont été réalisées par cet agent.

Blog

Articles similaires