Skip to content
All articles

iPhone Duo Hinge State: onHingeChange and UIHingeInteraction

Read the iPhone Duo hinge state and angle with onHingeChange or UIHingeInteraction in iOS 27.1, use it for effects and game controls, and see games that do.

By AppleDuo EditorialPublished 6 min read

Also available in:DeutschEspañolFrançais日本語Türkçe

On this page
  1. What hinge states does iPhone Duo report?
  2. How do I use .onHingeChange in SwiftUI?
  3. How do I observe the hinge in UIKit with UIHingeInteraction?
  4. Should the hinge state drive my layout?
  5. How should I design for tabletop mode?
  6. Which games turn the hinge into a control?
  7. Key takeaways

iPhone Duo is the first iPhone with a hinge, and iOS 27.1 lets your app read it. You can find out whether the device is closed, partly open or fully open, and follow the exact hinge angle as someone folds it. This guide covers the iPhone Duo hinge state APIs in SwiftUI and UIKit, when to use them, and when not to, with games that already turn the fold into a control.

The details come from Apple's documentation, Apple's iPhone Duo Tech Talks and forum answers, and a post from iOS developer @sarunw. We haven't tested these APIs on hardware. They shipped in iOS 27.1 with Xcode 27.1, so names and behavior can still change in later releases.

What hinge states does iPhone Duo report?

As @sarunw summarizes, "There are 3 hinge states: closed, partiallyOpen, and fullyOpen." Apple's Leverage multiple displays and scenes on iPhone Duo Tech Talk describes the same "high-level hinge status," and adds that the API also provides "continuous updates of the hinge angle."

Apple's documentation says the status is "determined by the system based on the current angle and device orientation." In other words, you get a simple state for decisions and a precise angle for anything that should move smoothly.

StatusSwiftUI (DeviceHinge.Status)UIKit (UIHinge.Status)Apple's description
Closed.closed.closedThe hinge is closed
Partly open.partiallyOpen.partiallyOpenThe hinge is partially open
Fully open.fullyOpen.fullyOpenOpen as far as the device allows
Unknownnot listed.unknownThe status is unknown

The angle type differs by framework. In SwiftUI, DeviceHinge.angle is an Angle. In UIKit, UIHinge.angle is a CGFloat in radians.

How do I use .onHingeChange in SwiftUI?

The SwiftUI API is onHingeChange(isEnabled:_:), available in iOS 27.1. Its action receives two DeviceHingeContext values, the previous one and the new one. Each context has an optional hinge of type DeviceHinge, which exposes angle and status.

This example from Apple's documentation stores the hinge in state and shows a fallback when no hinge is available:

@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
    }
}

A nil hinge means the device doesn't have one, so always handle that case. The isEnabled parameter defaults to true.

Using the old and new values

Because the closure gets both contexts, you can detect a transition, such as the moment the device closes. This is our own sketch built only on the documented types:

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

game.closeLid() stands in for your own code. Comparing old and new values avoids running the same action twice when only the angle changes.

How do I observe the hinge in UIKit with UIHingeInteraction?

In UIKit, add a UIHingeInteraction to a view. Its handler runs "when the hinge state changes, or when the interaction moves between hierarchies." When the view leaves a hierarchy that provides hinge updates, the update's hinge is nil. Apple's sample:

override func viewDidLoad() {
    super.viewDidLoad()

    let interaction = UIHingeInteraction { [weak self] _, update in
        guard let self else { return }
        // A nil `hinge` indicates the interaction has left a
        // hierarchy that provides hinge updates.
        guard let hinge = update.hinge else {
            handleHingeUnavailable()
            return
        }

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

    view.addInteraction(interaction)
}

The interaction also has an isEnabled property. Don't look for hinge information in the trait collection. On the developer forums, an Apple engineer confirmed that there are no UITraitCollection traits for hinge posture.

Should the hinge state drive my layout?

No. This is the most important rule. Apple's Tech Talk says: "Hinge data is observed live, and is ideal for driving interactions or effects. For layout, use the arrangement and region APIs."

On the forums, an Apple Technology Evangelist listed four approaches, from easiest to most custom:

  1. Use a system container such as NavigationSplitView or UISplitViewController.
  2. If that isn't enough, try ArrangementView or UIArrangementViewController.
  3. Only if neither works, position views with the reserved region APIs.
  4. Don't use onHingeChange or the hinge interaction API for layout decisions.

For layout, Apple's forum guidance is to avoid device-specific logic and embrace size classes, which change when the device opens or closes. Our guides to iPhone Duo size classes, ArrangementView and reserved regions and the fold cover those tools. The fold's division region is active only when the device is folded, so reserved regions already tell you where the crease is.

Hinge events are for things that should react to motion: a zoom effect on a wallpaper, a cover that opens with the fold, or a game mechanic. Apple's Tech Talk builds a guitar app where a partly folded hinge works like a whammy bar:

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

The bend only applies in the .partiallyOpen state and resets otherwise. Apple doesn't show the body of calculatePitchBend, so the mapping from angle to effect is up to you.

How should I design for tabletop mode?

When iPhone Duo sits on a table "like a laptop with the inner display facing you," the lower half is a stable base and the upper half is easy to look at. Apple's "Design for iPhone Duo" Tech Talk suggests that "media can sit at the top, while tappable controls live on a stable base at the bottom."

There is a catch. Apple adds that a special layout for this pose should keep "all the same controls and general hierarchy as other poses," because "you don't want to tie functionality to a specific pose." For apps, that means tabletop mode can rearrange content, but every feature must still work when the device is flat or closed.

Games have more freedom, since the pose can be the fun part. Even so, it helps to offer a fallback. Marbles Unhinged, for example, says on the App Store that it also plays on any iPhone or iPad with an on-screen hinge.

Which games turn the hinge into a control?

Several iPhone Duo games already use the fold as an input. The descriptions below come from each game's App Store listing and press coverage. We don't know which APIs each developer used internally.

GameWhat the hinge does
Marbles UnhingedBend the top half and its floor becomes a ramp. The steeper the fold, the faster the roll.
ToastieFold the phone shut to close the toaster lid, then open it to check the sandwich.
Greens: Mini-golfFold it like a laptop and putt on the lower half while the upright half becomes a caddie camera.
Battlefleet DuoIn tabletop mode, your fleet is on the lower screen and enemy waters stand up in front of you, with face-to-face play for two.
DuometryAccording to MacRumors, you fold the device to match a target angle and lock in your guess.

These map neatly to the APIs. Toastie's lid is a status change to .closed. Marbles Unhinged's ramp is a continuous angle. Greens and Battlefleet Duo are tabletop layouts, where the upper half shows a view and the lower half takes touches. Duometry needs the raw angle.

You can browse more games that use the fold on Built for the Fold.

Key takeaways

  • iPhone Duo reports three hinge states, closed, partiallyOpen and fullyOpen, plus a continuous angle. UIKit also has unknown.
  • Use .onHingeChange in SwiftUI or UIHingeInteraction in UIKit. Both are new in iOS 27.1, and both give a nil hinge when none is available.
  • The SwiftUI closure gets old and new contexts, so you can react to transitions instead of every angle update.
  • Keep layout on size classes, system containers, ArrangementView and reserved regions. Use hinge data for effects, interactions and game mechanics.
  • Tabletop designs should put media on top and controls on the base, without hiding features in other poses.

Next, learn how to keep controls out of the crease in our reserved regions guide, or play the games above from Built for the Fold.

Frequently asked questions

What are the hinge states on iPhone Duo?

There are three: closed, partiallyOpen and fullyOpen. The system chooses the status from the current angle and the device orientation. The UIKit enum also includes an unknown case.

How do I read the hinge angle in SwiftUI?

Add .onHingeChange to a view. The closure receives the previous and the new hinge context, and the new context's hinge property gives you an angle and a status. The hinge is nil on devices that don't have one.

Should I use the hinge state to change my layout?

No. Apple says onHingeChange and the hinge interaction API should not be used for layout decisions. Use size classes, system containers, ArrangementView or reserved regions for layout, and keep hinge events for effects and interactions.

Is there a UITraitCollection trait for the hinge?

No. An Apple engineer confirmed on the developer forums that there are no trait collection traits for hinge posture. In UIKit, use UIHingeInteraction for hinge updates.

Which games use the iPhone Duo hinge as a control?

Examples include Marbles Unhinged, where folding turns the floor into a ramp, Toastie, where folding shut closes the toaster lid, Greens, which putts on the lower half in a laptop pose, Battlefleet Duo in tabletop mode, and Duometry, an angle-guessing game.

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

Make the fold part of your app.

We showcase apps and games that do something real with iPhone Duo. Send us yours with a link to it on the App Store, or see what other developers have built.

[email protected]