Skip to content
Tous les articles

État de la charnière de l'iPhone Duo : onHingeChange et UIHingeInteraction

Lisez l'état et l'angle de la charnière de l'iPhone Duo avec onHingeChange ou UIHingeInteraction (iOS 27.1) pour vos effets et commandes de jeu, exemples à l'appui.

Par la rédaction AppleDuoPublié le 6 min de lecture

Également disponible en:EnglishDeutschEspañol日本語Türkçe

Sur cette page
  1. Quels états de charnière l'iPhone Duo signale-t-il ?
  2. Comment utiliser .onHingeChange en SwiftUI ?
  3. Comment observer la charnière en UIKit avec UIHingeInteraction ?
  4. L'état de la charnière doit-il piloter ma mise en page ?
  5. Comment concevoir pour le mode sur table ?
  6. Quels jeux transforment la charnière en commande ?
  7. À retenir

L'iPhone Duo est le premier iPhone doté d'une charnière, et iOS 27.1 permet à votre app de la lire. Vous pouvez savoir si l'appareil est fermé, partiellement ouvert ou complètement ouvert, et suivre l'angle exact de la charnière pendant que l'utilisateur le plie. Ce guide présente les API d'état de charnière de l'iPhone Duo en SwiftUI et en UIKit, quand les utiliser et quand s'en abstenir, avec des jeux qui font déjà du pliage une commande.

Les informations proviennent de la documentation d'Apple, des Tech Talks d'Apple consacrés à l'iPhone Duo, de réponses sur les forums et d'une publication du développeur iOS @sarunw. Nous n'avons pas testé ces API sur un appareil réel. Elles sont arrivées avec iOS 27.1 et Xcode 27.1 : les noms et le comportement peuvent donc encore changer dans les prochaines versions.

Quels états de charnière l'iPhone Duo signale-t-il ?

Comme le résume @sarunw, « il y a 3 états de charnière : closed, partiallyOpen et fullyOpen ». Le Tech Talk d'Apple Leverage multiple displays and scenes on iPhone Duo décrit le même « état de charnière de haut niveau » et ajoute que l'API fournit aussi des « mises à jour continues de l'angle de la charnière ».

La documentation d'Apple précise que l'état est « déterminé par le système en fonction de l'angle actuel et de l'orientation de l'appareil ». Autrement dit, vous obtenez un état simple pour les décisions et un angle précis pour tout ce qui doit bouger de façon fluide.

ÉtatSwiftUI (DeviceHinge.Status)UIKit (UIHinge.Status)Description d'Apple
Fermé.closed.closedLa charnière est fermée
Partiellement ouvert.partiallyOpen.partiallyOpenLa charnière est partiellement ouverte
Complètement ouvert.fullyOpen.fullyOpenOuvert autant que l'appareil le permet
Inconnunon listé.unknownL'état est inconnu

Le type de l'angle diffère selon le framework. En SwiftUI, DeviceHinge.angle est un Angle. En UIKit, UIHinge.angle est un CGFloat en radians.

Comment utiliser .onHingeChange en SwiftUI ?

L'API SwiftUI est onHingeChange(isEnabled:_:), disponible dans iOS 27.1. Son action reçoit deux valeurs DeviceHingeContext, la précédente et la nouvelle. Chaque contexte possède un hinge optionnel de type DeviceHinge, qui expose angle et status.

Cet exemple tiré de la documentation d'Apple stocke la charnière dans un état et affiche une solution de repli lorsqu'aucune charnière n'est disponible :

@State private var hinge: DeviceHinge? = nil

var body: some View {
    VStack {
        if let hinge {
            AngleDisplayView(angle: hinge.angle)
            StatusDisplayView(status: hinge.status)
        } else {
            ContentUnavailableView(
                "Hinge Unavailable",
                systemImage: "rectangle.split.2x1")
        }
    }
    .onHingeChange { _, newContext in
        hinge = newContext.hinge
    }
}

Un hinge à nil signifie que l'appareil n'a pas de charnière : gérez donc toujours ce cas. Le paramètre isEnabled vaut true par défaut.

Utiliser l'ancienne et la nouvelle valeur

Comme la closure reçoit les deux contextes, vous pouvez détecter une transition, par exemple le moment où l'appareil se ferme. Voici notre propre ébauche, construite uniquement sur les types documentés :

.onHingeChange { oldContext, newContext in
    let wasClosed = oldContext.hinge?.status == .closed
    let isClosed = newContext.hinge?.status == .closed
    if !wasClosed && isClosed {
        game.closeLid()
    }
}

game.closeLid() représente votre propre code. Comparer l'ancienne et la nouvelle valeur évite d'exécuter deux fois la même action lorsque seul l'angle change.

Comment observer la charnière en UIKit avec UIHingeInteraction ?

En UIKit, ajoutez une UIHingeInteraction à une vue. Son gestionnaire s'exécute « lorsque l'état de la charnière change, ou lorsque l'interaction passe d'une hiérarchie à une autre ». Lorsque la vue quitte une hiérarchie qui fournit des mises à jour de charnière, le hinge de la mise à jour vaut nil. L'exemple d'Apple :

override func viewDidLoad() {
    super.viewDidLoad()

    let interaction = UIHingeInteraction { [weak self] _, update in
        guard let self else { return }
        // Un `hinge` nil indique que l'interaction a quitté une
        // hiérarchie qui fournit des mises à jour de charnière.
        guard let hinge = update.hinge else {
            handleHingeUnavailable()
            return
        }

        updateAngleDisplay(with: hinge.angle)
        updateStatusDisplay(with: hinge.status)
    }

    view.addInteraction(interaction)
}

L'interaction possède aussi une propriété isEnabled. Ne cherchez pas d'informations sur la charnière dans la trait collection. Sur les forums développeurs, un ingénieur d'Apple a confirmé qu'il n'existe aucun trait UITraitCollection pour la posture de la charnière.

L'état de la charnière doit-il piloter ma mise en page ?

Non. C'est la règle la plus importante. Le Tech Talk d'Apple l'énonce ainsi : « Les données de charnière sont observées en direct et sont idéales pour piloter des interactions ou des effets. Pour la mise en page, utilisez les API d'arrangement et de régions. »

Sur les forums, un Technology Evangelist d'Apple a listé quatre approches, de la plus simple à la plus personnalisée :

  1. Utilisez un conteneur système comme NavigationSplitView ou UISplitViewController.
  2. Si cela ne suffit pas, essayez ArrangementView ou UIArrangementViewController.
  3. Seulement si aucune des deux solutions ne fonctionne, positionnez les vues avec les API de régions réservées.
  4. N'utilisez pas onHingeChange ni l'API d'interaction de charnière pour les décisions de mise en page.

Pour la mise en page, Apple recommande sur les forums d'éviter toute logique propre à un appareil et de s'appuyer sur les size classes, qui changent lorsque l'appareil s'ouvre ou se ferme. Nos guides sur les size classes de l'iPhone Duo, ArrangementView et les régions réservées et le pli présentent ces outils. La région de division du pli n'est active que lorsque l'appareil est plié : les régions réservées vous indiquent donc déjà où se trouve le pli.

Les événements de charnière servent à ce qui doit réagir au mouvement : un effet de zoom sur un fond d'écran, une couverture qui s'ouvre avec le pli ou une mécanique de jeu. Le Tech Talk d'Apple construit une app de guitare où une charnière partiellement pliée fonctionne comme un vibrato (whammy bar) :

.onHingeChange { _, context in
    if let hinge = context.hinge, hinge.status == .partiallyOpen {
        pitchBend = calculatePitchBend(angle: hinge.angle)
    }
    else {
        pitchBend = 0
    }
}

L'effet ne s'applique qu'à l'état .partiallyOpen et se réinitialise sinon. Apple ne montre pas le corps de calculatePitchBend : la correspondance entre l'angle et l'effet est donc à votre charge.

Comment concevoir pour le mode sur table ?

Lorsque l'iPhone Duo est posé sur une table « comme un ordinateur portable, l'écran interne tourné vers vous », la moitié inférieure forme une base stable et la moitié supérieure est facile à regarder. Le Tech Talk d'Apple « Design for iPhone Duo » suggère que « les médias peuvent se placer en haut, tandis que les commandes tactiles se trouvent sur une base stable en bas ».

Il y a cependant une limite. Apple ajoute qu'une mise en page spéciale pour cette position doit conserver « les mêmes commandes et la même hiérarchie générale que les autres positions », car « il ne faut pas lier une fonctionnalité à une position précise ». Pour les apps, cela signifie que le mode sur table peut réorganiser le contenu, mais que chaque fonctionnalité doit toujours fonctionner lorsque l'appareil est à plat ou fermé.

Les jeux ont plus de liberté, puisque la position peut faire partie du plaisir. Même dans ce cas, il est utile de proposer une solution de repli. Marbles Unhinged, par exemple, précise sur l'App Store qu'il se joue aussi sur n'importe quel iPhone ou iPad avec une charnière à l'écran.

Quels jeux transforment la charnière en commande ?

Plusieurs jeux iPhone Duo utilisent déjà le pliage comme moyen de contrôle. Les descriptions ci-dessous proviennent de la fiche App Store de chaque jeu et de la couverture presse. Nous ne savons pas quelles API chaque développeur a utilisées en interne.

JeuCe que fait la charnière
Marbles UnhingedPliez la moitié supérieure et son sol devient une rampe. Plus le pli est prononcé, plus la bille roule vite.
ToastieFermez le téléphone pour refermer le couvercle du grille-pain, puis ouvrez-le pour vérifier le sandwich.
Greens: Mini-golfPliez-le comme un ordinateur portable et jouez sur la moitié inférieure pendant que la moitié relevée devient une caméra de caddie.
Battlefleet DuoEn mode sur table, votre flotte est sur l'écran du bas et les eaux ennemies se dressent devant vous, avec un mode face à face à deux joueurs.
DuometrySelon MacRumors, vous pliez l'appareil pour atteindre un angle cible et validez votre estimation.

Ces exemples correspondent bien aux API. Le couvercle de Toastie est un changement d'état vers .closed. La rampe de Marbles Unhinged est un angle continu. Greens et Battlefleet Duo sont des mises en page sur table, où la moitié supérieure affiche une vue et la moitié inférieure reçoit les touchers. Duometry a besoin de l'angle brut.

Vous pouvez découvrir d'autres jeux qui exploitent le pliage sur Built for the Fold.

À retenir

  • L'iPhone Duo signale trois états de charnière, closed, partiallyOpen et fullyOpen, ainsi qu'un angle continu. UIKit propose aussi unknown.
  • Utilisez .onHingeChange en SwiftUI ou UIHingeInteraction en UIKit. Les deux sont nouveaux dans iOS 27.1, et les deux renvoient un hinge à nil lorsqu'aucune charnière n'est disponible.
  • La closure SwiftUI reçoit l'ancien et le nouveau contexte : vous pouvez ainsi réagir aux transitions plutôt qu'à chaque mise à jour d'angle.
  • Confiez la mise en page aux size classes, aux conteneurs système, à ArrangementView et aux régions réservées. Utilisez les données de charnière pour les effets, les interactions et les mécaniques de jeu.
  • Les designs pour le mode sur table doivent placer les médias en haut et les commandes sur la base, sans masquer de fonctionnalités dans les autres positions.

Ensuite, découvrez comment garder les commandes hors du pli dans notre guide des régions réservées, ou jouez aux jeux ci-dessus depuis Built for the Fold.

Questions fréquentes

Quels sont les états de charnière de l'iPhone Duo ?

Il y en a trois : closed, partiallyOpen et fullyOpen. Le système choisit l'état en fonction de l'angle actuel et de l'orientation de l'appareil. L'enum UIKit inclut aussi un cas unknown.

Comment lire l'angle de la charnière en SwiftUI ?

Ajoutez .onHingeChange à une vue. La closure reçoit le contexte de charnière précédent et le nouveau, et la propriété hinge du nouveau contexte vous donne un angle et un état. hinge vaut nil sur les appareils qui n'ont pas de charnière.

Faut-il utiliser l'état de la charnière pour modifier ma mise en page ?

Non. Apple indique qu'onHingeChange et l'API d'interaction de charnière ne doivent pas servir aux décisions de mise en page. Utilisez les size classes, les conteneurs système, ArrangementView ou les régions réservées pour la mise en page, et réservez les événements de charnière aux effets et aux interactions.

Existe-t-il un trait UITraitCollection pour la charnière ?

Non. Un ingénieur d'Apple a confirmé sur les forums développeurs qu'il n'existe aucun trait de trait collection pour la posture de la charnière. En UIKit, utilisez UIHingeInteraction pour recevoir les mises à jour de la charnière.

Quels jeux utilisent la charnière de l'iPhone Duo comme commande ?

Parmi les exemples : Marbles Unhinged, où plier l'appareil transforme le sol en rampe, Toastie, où le fermer referme le couvercle du grille-pain, Greens, où l'on joue sur la moitié inférieure en position ordinateur portable, Battlefleet Duo en mode sur table, et Duometry, un jeu où il faut deviner un angle.

Sources

  1. Leverage multiple displays and scenes on iPhone Duo · Apple Developer (Tech Talk)
  2. Design for iPhone Duo · Apple Developer (Tech Talk)
  3. onHingeChange(isEnabled:_:) · Apple Developer Documentation
  4. DeviceHinge · Apple Developer Documentation
  5. UIHingeInteraction · Apple Developer Documentation
  6. UIHinge · Apple Developer Documentation
  7. Strike a pose with adaptive layouts on iPhone Duo · Apple Developer (Tech Talk)
  8. Recommended source of truth for adapting UIKit layouts on iPhone Duo · Apple Developer Forums
  9. Best practice for responding to the hinge angle in SwiftUI · Apple Developer Forums
  10. Hinge state adaptation in UIKit: Trait collections vs. view layout callbacks · Apple Developer Forums
  11. What can the APIs added in iOS 27.1 for iPhone Duo do? · DevelopersIO (Classmethod)
  12. iPhone Duo Apps, What Changes in Your Code and What to Do With Old Ones · Pasquale Pillitteri
  13. The iPhone Duo Can Be a Tiny Mac, a Toaster, and a Nintendo DS · MacRumors
  14. There are 3 hinge states: closed, partiallyOpen, and fullyOpen · @sarunw on X

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

[email protected]