ArrangementView for iPhone Duo

Build split and overlay layouts for iPhone Duo with SwiftUI ArrangementView — primary/secondary content, .split, .overlay, and placement rules.

Last updated

Quick answer

Give ArrangementView primary and secondary content, then set .arrangementViewStyle(.split) or .overlay (the default is .split). Place it inside a NavigationStack as a major-region container — not inside a List, ScrollView, or NavigationSplitView. Existing size-class layouts still work on iOS 27.1; adopt this API when two related regions should move as Duo's geometry changes.

What ArrangementView is

ArrangementView is a SwiftUI container introduced with iOS 27.1: you hand it two related regions — primary and secondary — and the system chooses how they share the area as the window resizes or the device folds.

It is not a new layout engine you implement yourself. You are not replacing Layout or AnyLayout. You describe a relationship; presentation is the system's job. The UIKit counterpart is UIArrangementViewController.

DuoSessionView.swift
ArrangementView {
    PlayerView()
} secondary: {
    TranscriptView()
}
.arrangementViewStyle(.split)

Split style

.split is the default: it divides the available area so both children stay independently visible — horizontal when the container is wider than it is tall, vertical when it is taller than it is wide.

Restrict the axis when only one direction is useful. If the preferred axis cannot be honored — a narrow Split View pane, for example — the system may show only one of the two views instead of forcing a cramped split.

InspectorSplit.swift
ArrangementView {
    CanvasView()
} secondary: {
    InspectorView()
}
.arrangementViewStyle(.split.axes(.horizontal))

Apple recommendation

Prefer .split whenever both regions must remain independently visible and independently scrollable — a player next to a transcript, a canvas next to an inspector. That is the relationship .split is built for.

Overlay style

.overlay treats children as foreground and background: they can stack, then sit side by side when geometry changes — use it when one region may sit above the other rather than claiming a permanent column.

PlaybackOverlay.swift
ArrangementView {
    VideoSurface()
} secondary: {
    PlaybackChrome()
}
.arrangementViewStyle(.overlay)

Overlay z-index

Read @Environment(\.overlayArrangementZIndex) in the overlay child — a zIndex greater than 0 means that child is in front and should use its compact or collapsed presentation. Do not infer front/back from device model or a hardcoded fold angle.

OverlayChrome.swift
struct PlaybackChrome: View {
    @Environment(\.overlayArrangementZIndex) private var zIndex

    var body: some View {
        if zIndex > 0 {
            CompactControls()
        } else {
            ExpandedControls()
        }
    }
}

Split vs overlay

Choose the style from the relationship, not from the hardware. Split keeps both regions independently on screen. Overlay lets one sit above the other and collapse when it is in front.

  • If the natural sketch is an HStack or VStack, start with .split.
  • If the natural sketch is a ZStack, start with .overlay.
  • Keep list-detail navigation in NavigationSplitView; use ArrangementView for two content regions that should move together.

You can still use size classes and geometry for the rest of the app. ArrangementView is the piece that owns the two regions whose placement should change with Duo's fold and window size.

Placement rules

Put ArrangementView inside a NavigationStack as a major-region container — not inside a List, ScrollView, or NavigationSplitView. Those parents already own scrolling and column collapsing, and they will clip or ignore the arrangement.

RootNavigation.swift
NavigationStack {
    ArrangementView {
        PlayerView()
    } secondary: {
        TranscriptView()
    }
    .arrangementViewStyle(.split)
    .navigationTitle("Session")
}

Common mistake

Don't wrap ArrangementView around a List row, and don't branch on device identity to decide split vs overlay. A row wrapper cannot be a major-region container, and if device == .iPhoneDuo { .overlay } breaks the moment the window is resized or a new posture ships. Declare the relationship; let the style and the environment do the rest.

Frequently asked questions

How do I use ArrangementView in SwiftUI on iPhone Duo?

Pass two related regions as primary and secondary content, then pick a style with .arrangementViewStyle(.split) or .overlay. The default is .split. Put the ArrangementView inside a NavigationStack so the system can treat it as a major-region container.

What is the difference between ArrangementView split and overlay?

Split divides the available area so both children stay independently visible. Overlay treats them as foreground and background: they can stack, then sit side by side when geometry changes. If you would have written an HStack or VStack, start with split. If you would have written a ZStack, start with overlay.

Does ArrangementView replace NavigationSplitView or Layout?

No. ArrangementView declares a relationship between two regions and lets the system choose presentation as the window and fold change. It is not a drop-in for NavigationSplitView, List, ScrollView, the Layout protocol, or AnyLayout. Keep list-detail navigation in NavigationSplitView; use ArrangementView for two content regions that should move together.

Do existing size-class SwiftUI apps need ArrangementView on iOS 27.1?

No. Apps that already adapt to size classes continue to run without it. Adopt ArrangementView when the screen naturally has two related regions whose placement should change with geometry or fold — a player and a transcript, an inspector, or controls that sit over content.

How do I detect which overlay child is in front on iPhone Duo?

Read @Environment(\.overlayArrangementZIndex) in the child. A zIndex greater than 0 means that child is in front and should use its compact or collapsed presentation. Do not infer front/back from device model or a hardcoded fold angle.

Apps using Split View