Développeurs
Sheets sur iPhone Duo : placement et coins arrondis
Présentation des sheets sur iPhone Duo : presentationPlacement pour une sheet à gauche, à droite ou centrée, et concentricCornerRadii pour aligner les coins.
Par la rédaction AppleDuoPublié le 9 min de lecture
Sur cette page
- Où les sheets apparaissent-elles par défaut sur iPhone Duo ?
- Comment utiliser presentationPlacement en SwiftUI ?
- Quel placement de sheet choisir ?
- Pourquoi une sheet épouse-t-elle les coins de l'iPhone Duo ?
- Comment aligner les coins de l'écran avec concentricCornerRadii ?
- Quand utiliser UnevenRoundedRectangle ?
- Quels sont les pièges courants avec les sheets sur iPhone Duo ?
- Ce qu'il faut retenir
Sur un iPhone classique, une sheet glisse depuis le bas et occupe toute la largeur. Sur iPhone Duo, la présentation des sheets fonctionne autrement : sur le grand écran intérieur, une sheet peut flotter au centre ou se caler contre le bord leading ou trailing, et son contour suit les coins irréguliers de l'écran. Ce guide présente les API d'iOS 27 qui contrôlent la position d'une sheet, la façon dont le système la traite dans chaque posture, et comment aligner vos propres formes arrondies sur le matériel.
Tout ce qui suit provient de la documentation d'Apple, des Tech Talks consacrés à l'iPhone Duo, des réponses d'ingénieurs Apple sur les forums développeurs et des publications du développeur iOS @sarunw. L'équipe AppleDuo n'a pas exécuté ce code sur l'appareil. Les API sont arrivées avec iOS 27 et Xcode 27, et certains détails peuvent changer d'une version à l'autre.
Où les sheets apparaissent-elles par défaut sur iPhone Duo ?
Les sheets s'adaptent d'elles-mêmes à chaque posture. Dans le Tech Talk Prepare your app for iPhone Duo, Apple explique que les sheets de l'écran extérieur peuvent disposer leurs boutons de barre verticalement, et que les sheets de l'écran intérieur sont centrées. Les popovers, menus contextuels et alertes s'adaptent eux aussi.
Un ingénieur DTS d'Apple a apporté des précisions dans un fil des forums développeurs : toutes les sheets passent sur le bord leading quand l'appareil est plié, et s'affichent au centre quand l'écran intérieur est ouvert à plat.
Les barres à l'intérieur d'une sheet suivent leurs propres règles. L'article d'Apple Preparing your app for iPhone Duo indique que l'écran extérieur affiche par défaut les barres d'une sheet verticalement. Sur l'écran intérieur, la barre d'outils est horizontale pour les sheets centrées ou leading, et verticale pour les sheets trailing.
| Emplacement | Position par défaut de la sheet | Barres dans la sheet |
|---|---|---|
| Écran extérieur (fermé) | S'adapte automatiquement | Verticales par défaut |
| Écran intérieur, partiellement plié | Bord leading (selon le DTS d'Apple) | Horizontales pour un placement leading |
| Écran intérieur, ouvert à plat | Centre | Horizontales pour un placement centré |
| Écran intérieur, placement trailing | Bord trailing (si vous le demandez) | Verticales |
Si vous ne voulez pas de barre verticale dans une sheet, désactivez-la avec toolbarVerticalBehavior(_:) en SwiftUI ou preferredVerticalBarBehavior en UIKit. Notre guide sur la barre d'outils verticale de l'iPhone Duo explique comment ces barres sont construites et comment les éléments débordent.
Comment utiliser presentationPlacement en SwiftUI ?
iOS 27 ajoute le modificateur presentationPlacement(_:) et le type PresentationPlacement. Vous l'appliquez au contenu de la sheet, à côté de modificateurs comme presentationDetents. Voici l'exemple de la documentation d'Apple, qui laisse visible une plus grande partie de la carte derrière la sheet :
Map()
.sheet(isPresented: $isPresented) {
PlaceDetailView()
.presentationDetents([.medium, .large])
.presentationPlacement(.leading)
}
PresentationPlacement propose quatre valeurs statiques. Apple précise que seules les présentations de type sheet les respectent ; les popovers, alertes et menus ignorent ce modificateur.
| Valeur | Ce que dit la documentation d'Apple |
|---|---|
.automatic | Le système détermine le placement (valeur par défaut) |
.center | Centre la présentation dans la vue qui la présente |
.leading | Place la présentation sur le bord leading de la vue qui la présente |
.trailing | Place la présentation sur le bord trailing de la vue qui la présente |
Leading et trailing dépendent du sens de mise en page : dans une langue qui s'écrit de droite à gauche, .leading devrait donc placer la sheet à droite. C'est différent de la barre verticale qui, comme le note @sarunw, suit le matériel et non le sens de lecture. Testez les deux sens si votre app est localisée en arabe ou en hébreu.
Et en UIKit ?
En UIKit, définissez la propriété preferredPlacement sur le UISheetPresentationController du view controller présenté. L'article d'Apple la cite comme l'équivalent UIKit de presentationPlacement(_:), et un Technology Evangelist d'Apple l'a indiquée dans ce fil du forum comme le moyen d'influencer la façon dont les sheets s'adaptent à la manière dont on tient l'iPhone Duo. Vérifiez les noms exacts des valeurs dans les en-têtes UIKit de Xcode 27 avant d'écrire le code.
Quel placement de sheet choisir ?
Commencez par .automatic. Le système déplace déjà les sheets entre le centre et le bord leading quand l'appareil se plie, et il choisit la bonne orientation de barre dans chaque cas. Ne forcez le placement que si vous avez une raison de le faire.
Bonnes raisons de choisir un côté :
- Garder le contenu principal visible. L'exemple d'Apple utilise
.leadingpour une fiche de lieu par-dessus une carte. Appliquez la même idée à une sheet de type inspecteur à côté d'une photo, d'un document ou d'un plateau de jeu. - Éloigner la sheet de la barre verticale. Dans certaines postures, l'écran intérieur place les barres le long d'un bord. Si votre vue principale utilise déjà ce bord, une sheet de l'autre côté laisse la barre d'outils dégagée. N'oubliez pas qu'une sheet trailing reçoit sa propre barre d'outils verticale.
- Rester à côté du contenu que la sheet modifie. Une sheet de mise en forme placée à côté du paragraphe qu'elle modifie est plus pratique qu'une sheet qui le recouvre.
Choisissez .center pour des tâches ciblées et autonomes, comme une connexion, un partage ou un formulaire de réglages, quand rien de ce qui se trouve derrière la sheet n'a d'importance.
Le placement peut-il changer selon la posture ?
Pas tout seul. Un ingénieur Apple a confirmé sur les forums que le placement défini s'applique en permanence, pas seulement en position pliée, et qu'il n'existe pas d'ordre de repli du type « centre, puis trailing ». La solution proposée consiste à détecter une reserved region de division active et à choisir vous-même le placement :
struct PlaceMapView: View {
@State private var isPresented = true
var body: some View {
GeometryReader { proxy in
// Division active = le pli est utilisé (partiellement plié)
let isFolded = !proxy.reservedRegions(kind: .division).isEmpty
Map()
.sheet(isPresented: $isPresented) {
PlaceDetailView()
.presentationDetents([.medium, .large])
.presentationPlacement(isFolded ? .trailing : .automatic)
}
}
}
}
Il s'agit d'une ébauche construite à partir de deux API documentées, reservedRegions(kind:) et presentationPlacement(_:), et non de code publié par Apple. Notre guide sur les reserved regions et le pli détaille les régions actives et inactives, et celui sur les états de charnière et onHingeChange explique comment écouter directement les changements de posture.
Pourquoi une sheet épouse-t-elle les coins de l'iPhone Duo ?
Comme le souligne @sarunw, une sheet sur iPhone Duo suit les coins irréguliers de l'appareil. Les sheets système, les popovers et les autres conteneurs utilisent des coins concentriques : chaque courbe intérieure partage son centre avec la courbe extérieure, de sorte que l'écart entre les deux reste constant tout autour.
Apple indique dans le Tech Talk que les API de concentricité introduites dans iOS 26 ont été mises à jour pour fonctionner avec les formes d'écran de l'iPhone Duo. En SwiftUI, cela signifie ConcentricRectangle ; en UIKit, UICornerConfiguration. L'exemple SwiftUI du Tech Talk se résume à une forme remplie :
ConcentricRectangle()
.fill(Color.green)
.padding(8.0)
.ignoresSafeArea()
Si vous utilisez les sheets système et ces formes, vous obtenez gratuitement des coins assortis. Le problème apparaît quand vous dessinez vos propres panneaux avec un cornerRadius codé en dur, réglé pour un autre iPhone.
Comment aligner les coins de l'écran avec concentricCornerRadii ?
iOS 27 ajoute concentricCornerRadii à GeometryProxy. Contrairement à ConcentricRectangle, il ne dessine rien : il renvoie un RectangleCornerRadii? que vous pouvez utiliser pour du dessin personnalisé, des animations ou vos propres formes. Une méthode associée, concentricCornerRadii(in:), fait de même pour un sous-rectangle de la vue.
La documentation d'Apple donne la règle : le rayon de chaque coin est égal au rayon du coin du conteneur moins la distance entre le coin de la vue et celui du conteneur. Les coins éloignés des coins du conteneur obtiennent zéro, et le résultat est plafonné au plus grand rayon possible pour la vue.
@sarunw donne un exemple chiffré : sur iPhone 18 Pro, le coin de l'écran mesure 62 points, donc une vue située à 16 points obtient 62 − 16 = 46 points. Ce chiffre de 62 points vient de sa publication ; Apple ne publie pas de rayons d'angle par appareil dans les pages que nous avons consultées.
| Coin de l'écran | Retrait par rapport au coin | Rayon concentrique |
|---|---|---|
| 62 pt (iPhone 18 Pro, selon @sarunw) | 16 pt | 46 pt |
| 62 pt | 8 pt | 54 pt |
| 62 pt | 62 pt ou plus | 0 pt |
Les deux dernières lignes appliquent la formule documentée au même coin ; ce ne sont pas des mesures distinctes. Sur iPhone Duo, les coins ne sont pas uniformes, et c'est précisément pour cela qu'il vaut mieux lire la valeur que la coder en dur.
La propriété renvoie nil si aucune forme de conteneur n'est définie, ou si la forme ne fournit pas assez d'informations sur ses coins. L'exemple d'Apple en définit une explicitement avec containerShape(_:). Gérez toujours nil avec une valeur de repli raisonnable :
struct FloatingPanel: View {
private let fallback = RectangleCornerRadii(
topLeading: 16, bottomLeading: 16,
bottomTrailing: 16, topTrailing: 16
)
var body: some View {
GeometryReader { proxy in
UnevenRoundedRectangle(
cornerRadii: proxy.concentricCornerRadii ?? fallback,
style: .continuous
)
.fill(.thinMaterial)
}
.padding(16)
.ignoresSafeArea()
}
}
Le panneau est placé à 16 points des bords, demande ses rayons concentriques au proxy et les dessine avec UnevenRoundedRectangle. Si le système ne parvient pas à résoudre une forme de conteneur, le panneau se rabat sur un rayon uniforme de 16 points.
Quand utiliser UnevenRoundedRectangle ?
UnevenRoundedRectangle dessine un rectangle avec un rayon différent pour chaque coin. Il n'est pas nouveau dans iOS 27 (la documentation d'Apple l'indique depuis iOS 16), mais c'est le complément naturel de concentricCornerRadii, car une vue proche d'un coin de l'écran a besoin d'un grand rayon de ce côté et d'un petit rayon partout ailleurs.
Vous pouvez passer une valeur RectangleCornerRadii, comme ci-dessus, ou nommer chaque coin :
UnevenRoundedRectangle(
topLeadingRadius: 46,
bottomLeadingRadius: 46,
bottomTrailingRadius: 12,
topTrailingRadius: 12,
style: .continuous
)
.fill(.background.secondary)
Cette forme convient à un panneau personnalisé fixé au bord leading : les deux coins extérieurs suivent l'écran, et les deux coins intérieurs restent serrés. Préférez les valeurs calculées par concentricCornerRadii à des nombres littéraux comme 46, qui ne valent que pour un appareil et un retrait donnés.
| Besoin | Outil | Depuis |
|---|---|---|
| Une forme dessinée par le système qui épouse son conteneur | ConcentricRectangle | iOS 26 |
| Uniquement les rayons, pour du dessin personnalisé | GeometryProxy.concentricCornerRadii | iOS 27 |
| Votre propre rayon pour chaque coin | UnevenRoundedRectangle | iOS 16 (selon la documentation d'Apple) |
Quels sont les pièges courants avec les sheets sur iPhone Duo ?
- Forcer le placement partout. Comme un placement fixe s'applique dans toutes les postures, une sheet qui rend bien à moitié pliée peut paraître étrange ouverte à plat. Utilisez
.automaticsauf si un écran exige autre chose. - Contrôleurs de présentation personnalisés. Une présentation faite maison ne bénéficie ni de l'adaptation du système aux postures ni des coins concentriques. Préférez les sheets système avec detents.
- Rayons d'angle codés en dur. Un rayon copié d'un ancien iPhone ne correspondra pas aux coins de l'iPhone Duo. Lisez
concentricCornerRadiiou utilisezConcentricRectangle. - Marges inégales dans la sheet. À côté d'une barre verticale, les marges diffèrent selon le côté. Notre article sur les safe areas et les marges de contenu présente
contentMargins(for:edges:). - Toolchains bêta. Un développeur a signalé un plantage au lancement (« Symbol not found » pour
PresentationPlacement.leading) sur un appareil avec Xcode 27 beta 6, malgré une vérification de disponibilité. Aucune cause n'est confirmée dans ce fil ; compilez avec la version finale de Xcode 27 et un OS correspondant avant de traiter le problème comme un bug de votre code.
Vérifiez chaque sheet dans chaque posture : fermé, partiellement plié et ouvert à plat, dans les deux orientations. Notre checklist pour préparer votre app à l'iPhone Duo liste les autres vérifications utiles.
Ce qu'il faut retenir
- Sur iPhone Duo, les sheets s'adaptent par défaut : centrées sur l'écran intérieur ouvert, déplacées sur le bord leading en position pliée, avec des barres verticales sur l'écran extérieur.
presentationPlacement(_:)(SwiftUI) etpreferredPlacement(UIKit), tous deux nouveaux dans iOS 27, définissent une sheet leading, trailing ou centrée. Seules les sheets les respectent, et le placement s'applique dans toutes les postures.- Pour changer de placement selon la posture, vérifiez la présence d'une division active avec
reservedRegions(kind:)et choisissez vous-même la valeur. concentricCornerRadiisurGeometryProxy(iOS 27) renvoie des rayons qui partagent leur centre avec les coins du conteneur ; gérez le casnil.- Dessinez ces rayons avec
UnevenRoundedRectangle, ou utilisezConcentricRectanglesi vous avez seulement besoin de la forme.
Lisez ensuite comment les barres passent sur le bord vertical, puis découvrez ce que les développeurs ont créé dans notre sélection de jeux conçus pour le pli.
Questions fréquentes
Comment placer une sheet côté leading ou trailing sur iPhone Duo ?
Appliquez presentationPlacement(.leading) ou presentationPlacement(.trailing) au contenu de la sheet en SwiftUI. En UIKit, définissez la propriété preferredPlacement du UISheetPresentationController du view controller. Seules les présentations de type sheet respectent ce placement.
Où une sheet apparaît-elle par défaut sur iPhone Duo ?
Avec le placement automatique, c'est le système qui décide. Apple indique que les sheets sont centrées sur l'écran intérieur, et un ingénieur Apple a précisé sur les forums développeurs que les sheets passent sur le bord leading quand l'appareil est plié et s'affichent au centre quand l'écran intérieur est ouvert à plat.
presentationPlacement change-t-il quand l'appareil se plie ?
Non. Selon un ingénieur Apple sur les forums développeurs, le placement que vous définissez s'applique en permanence, pas seulement en position pliée. Pour l'adapter à chaque posture, vérifiez la présence d'une reserved region de division active et choisissez vous-même le placement.
Que renvoie concentricCornerRadii ?
Il renvoie les rayons d'angle dont une vue a besoin pour que ses coins partagent leur centre avec ceux du conteneur, sous forme de valeur RectangleCornerRadii. Il renvoie nil si aucune forme de conteneur n'est définie ou si la forme ne fournit pas assez d'informations sur ses coins. C'est nouveau dans iOS 27.
Quelle différence entre UnevenRoundedRectangle et ConcentricRectangle ?
UnevenRoundedRectangle dessine un rectangle avec les rayons que vous fournissez pour chaque coin. ConcentricRectangle, introduit dans iOS 26, calcule pour vous des coins concentriques et dessine la forme. concentricCornerRadii se situe entre les deux : il renvoie uniquement les rayons, que vous pouvez passer à UnevenRoundedRectangle ou à un Path.
Sources
- presentationPlacement(_:) · Apple Developer Documentation
- PresentationPlacement · Apple Developer Documentation
- Preparing your app for iPhone Duo · Apple Developer Documentation
- Prepare your app for iPhone Duo (Tech Talk) · Apple Developer
- concentricCornerRadii · Apple Developer Documentation
- UnevenRoundedRectangle · Apple Developer Documentation
- Modal on trailing (DTS answer on sheet placement) · Apple Developer Forums
- Controlling sheet presentation across iPhone Duo poses · Apple Developer Forums
- A sheet can sit on the leading side, the trailing side, or the center · @sarunw on X
- The sheet on iPhone Duo curves around the device's uneven corners · @sarunw on X
- iOS 27 adds concentricCornerRadii to GeometryProxy · @sarunw on X
- 62 − 16 = 46: how a concentric corner is calculated · @sarunw on X
- Need a different radius on each corner? Use UnevenRoundedRectangle · @sarunw on X
- The vertical bar follows the hardware, not the reading direction · @sarunw on X
- .presentationPlacement(.leading) does not work! · Apple Developer Forums
Faites du pli une partie de votre app.
Nous présentons les apps et les jeux qui exploitent vraiment l’iPhone Duo. Envoyez-nous la vôtre avec un lien vers l’App Store, ou découvrez ce que d’autres ont créé.