開発者向け
ArrangementView:iPhone Duo での split と overlay
SwiftUI の ArrangementView が iPhone Duo でメインとセカンダリのビューをどう配置するかを解説。split と overlay の違い、比率指定、ヒンジ、各ペインのサイズクラスまで。
AppleDuo 編集部公開 14分で読めます
このページの内容
多くの画面は、実はセットになった2つのビューでできています。プレーヤーと再生キュー、会話と写真、ポッドキャストと文字起こしなどです。通常の iPhone ではこれらを縦に積みます。iPhone Duo の内側ディスプレイでは左右に並べたいところですし、ユーザーがデバイスを半分折りたたんだときには、どちらのビューも折り目をまたいでほしくありません。SwiftUI の ArrangementView は、この問題に対する Apple の答えです。このガイドでは、ArrangementView の役割、2つのスタイル、ヒンジ周りでのサイズの決まり方、そして代わりに NavigationSplitView を選ぶべき場面を解説します。
Apple のドキュメントでは、ArrangementView とそのスタイル、サイズ指定のモディファイアは iOS 27.1 以降で利用可能とされており、iPhone Duo のフル体験向けにビルドするには Xcode 27.1 が必要です。これらは新しい API なので、リリース間で詳細が変わる可能性があります。以下の内容はすべて、Apple のドキュメント、Tech Talk「Strike a pose with adaptive layouts on iPhone Duo」、そして iOS 開発者 Sarun Wongpatcharapakorn(@sarunw)の投稿に基づいています。私たちはこのコードを実機で動かしてはいません。
SwiftUI の ArrangementView とは?
ArrangementView は、プライマリとセカンダリのちょうど2つのビューを保持し、それらを自動的にレイアウトするコンテナです。Tech Talk で Apple は、arrangement をナビゲーションコンテナとコンテンツコンテナの間に位置する新しいレイヤーとして説明しています。
arrangement を動かすルールは3つの入力を読み取ります。ビューの水平・垂直のサイズクラス、アスペクト比、そして分割領域が有効かどうかです。iPhone Duo では、分割領域とは折り目のことです。これらの入力から、arrangement は各ビューを表示するかどうかと、どのフレームを与えるかを決めます。ここが HStack や VStack との大きな違いです。スタックは常にすべての子を表示しますが、arrangement は余裕がなければセカンダリビューを隠すことがあります。Apple のエンジニアは開発者フォーラムで、この折りたたみ(コラプス)は想定どおりの動作だと認めています。
UIKit にも同じ概念として UIArrangementViewController があり、プライマリとセカンダリのビューコントローラを受け取ります。この記事では SwiftUI に焦点を当てます。
アプリに ArrangementView を追加するには?
arrangement は2つのトレイリングクロージャで作成し、ナビゲーションコンテナの中に置きます。Tech Talk で Apple が使っている形は次のとおりです。
var body: some View {
NavigationStack {
ArrangementView {
PlayerView()
} secondary: {
UpNextView()
}
}
}
最初のクロージャがプライマリビュー、secondary: クロージャがセカンダリビューです。Sarun の図では「First View」と「Secondary View」と呼ばれていますが、同じものです。
配置する場所が重要です。ArrangementView は独自のナビゲーションを持たないので、ナビゲーションは内側ではなく外側に置きます。Apple のドキュメントでは、arrangement を scroll view、list、grid、navigation split view の中に入れることと、navigation split view や tab view を arrangement の中に入れることを避けるよう書かれています。
スタイルを選ぶには arrangementViewStyle(_:) を適用します。arrangement が使う軸を制限することもできます。
ArrangementView {
NowPlayingView()
} secondary: {
LyricsView()
}
.arrangementViewStyle(.split.axes(.horizontal))
指定しなかった軸では、arrangement はプライマリビューだけを表示します。
split と overlay、ArrangementView のスタイルはどちらを使うべき?
スタイルは2つあります。デフォルトのスタイルは split に解決され、overlay がもう一方の選択肢です。姿勢によっては同じ動作をしますが、まったく違う動作をする姿勢もあります。以下の用語はデバイスの状態に従います。「閉じた状態」は外側ディスプレイを使っている状態、「半開き」は内側ディスプレイで部分的に折りたたまれた状態、「開いた状態」はフラットな状態です。
| 姿勢 | split スタイル | overlay スタイル |
|---|---|---|
| 閉じた状態、縦向き | 上にプライマリ、下にセカンダリ | プライマリをセカンダリの上に重ねる |
| 閉じた状態、横向き | プライマリのみ | プライマリをセカンダリの上に重ねる |
| 半開き、本のような形 | 左右に並べ、プライマリが leading 側 | 左右に並べ、プライマリが trailing 側 |
| 半開き、ノートパソコンのような形 | 上下に積み、プライマリが上 | 上下に積み、プライマリが下 |
| 開いた状態、横向き | 左右に並べ、プライマリが leading 側 | プライマリをセカンダリの上に重ねる |
| 開いた状態、縦向き | 上下に積み、プライマリが上 | プライマリをセカンダリの上に重ねる |
Sarun は split をこうまとめています。split は「各ビューを左右に並べようとする」もので、スペースが足りなければ最初のビューだけが表示されます。overlay は「ほとんどの場合2つのビューを重ねる」もので、折りたたんだ状態では2つが左右に並び、First View が右側に来ます。これは split とは逆です。Apple のドキュメントでも同じ配置が説明されており、折りたたんだ横向きの姿勢では、overlay はセカンダリビューを leading 側、プライマリビューを trailing 側に置きます。これを反転させるには、プライマリビューに overlayArrangementEdge(.leading) を適用します。
どちらを選ぶかについての Apple のガイダンスはシンプルです。ポッドキャストと文字起こしのように、どちらのビューも覆い隠されるべきでないメインと詳細の関係には split を使います。動画の上の再生コントロールのように、前景と背景がはっきりしている場合は overlay を使います。現在のレイアウトが HStack や VStack なら split が自然な対応先で、ZStack なら overlay を使います。
overlay の arrangement では、ビューは自分の重なり順を読み取って表示を変えられます。Tech Talk では、値が0より大きいときにビューを折りたたんだ形に切り替えています。
struct PlayerControls: View {
@Environment(\.overlayArrangementZIndex)
private var zIndex: Int
var body: some View {
ControlsPanel(isCollapsed: zIndex > 0)
}
}
ControlsPanel はあなた自身のビューに置き換えてください。
iPhone Duo で splitArrangementLayoutRatio はどう動く?
デフォルトでは、split の arrangement は両方のビューを同じサイズにします。これを変えるには、どちらかのビューに splitArrangementLayoutRatio(_:) を適用します。引数は0から1の間のオプショナルな CGFloat です。Apple の例は次のとおりです。
ArrangementView {
ConversationView()
.splitArrangementLayoutRatio(0.3)
} secondary: {
PhotosView()
}
.arrangementViewStyle(.split.axes(.horizontal))
arrangement は、layoutPriority が最も高いビューから先に、その比率を使ってサイズを決めます。比率が残りのスペースより多くを求める場合、そのビューには残りのスペースが与えられます。比率の合計でスペースが余る場合は、優先度の高いビューが広がって埋めます。Apple は関連するモディファイアとして、最小・理想・最大の比率、splitArrangementLayoutSize による明示的なサイズ指定、splitArrangementFixedLayoutSize もドキュメント化しています。
重要な例外が1つあります。Sarun の報告によると、半開きの iPhone Duo では splitArrangementLayoutRatio が無視され、分割位置は常にヒンジ上で半分ずつになります。これは理にかなっています。30/70 の分割では、一方のペインの端が折り目をまたいでしまうからです。比率はフラットなディスプレイ向けに設計し、デバイスが折りたたまれたときは均等に分割されると想定してください。この動作は Apple のドキュメントには明記されていなかったので、iOS 27.2 で観察された動作として扱ってください。
均等な分割は、ペインのサイズが同じという意味ではありません。Sarun の図では、横向きの半開きデバイスでディスプレイの各半分が 475 ポイントで、ステータスバーが右端に沿って 84 ポイントを占めています。その結果、セカンダリペインは狭くなります。2つのペインが同じサイズだと決めつけず、常に与えられたサイズに合わせてレイアウトしてください。
折り目そのものがどう報告されるかは、予約領域で iPhone Duo の折り目を扱う方法を参照してください。
ArrangementView の各ペインのサイズクラスはどうなる?
arrangement の各ペインには独自のサイズクラスが与えられ、多くの場合ウインドウのサイズクラスとは異なります。Sarun が iOS 27.2 で計測した結果は次のとおりです。H は水平、V は垂直です。
| 姿勢とレイアウト | First view(H/V、ポイント) | Secondary view(H/V、ポイント) |
|---|---|---|
| 閉じた状態、縦向き、上下に積む | Compact/Compact、382 × 322 | Compact/Compact、382 × 322 |
| 閉じた状態、横向き | Compact/Compact、594 × 432 | 非表示 |
| 半開き、縦向き、折り目をまたいで上下に積む | Regular/Compact、669 × 373 | Regular/Compact、669 × 421 |
| 半開き、横向き、左右に並べる | Compact/Regular、455 × 635 | Compact/Regular、371 × 635 |
| 開いた状態、縦向き、上下に積む | Regular/Compact、669 × 417 | Regular/Compact、669 × 417 |
| 開いた状態、横向き、左右に並べる | Compact/Regular、433 × 635 | Compact/Regular、433 × 635 |
ここから2つのルールが導けます。1つ目は、分割する軸が compact になることです。左右に並べると各ペインの幅が compact になり、上下に積むと各ペインの高さが compact になります。2つ目は、内側ディスプレイでは半開きでも開いた状態でも、ペインは iPad の ArrangementView と同じサイズクラスを受け取ることです。
つまり、regular 幅の内側ディスプレイにあるペインでも、水平サイズクラスが compact と報告されることがあります。各ペインは自分自身の環境に反応するように作り、ペインの内側からウインドウのトレイトを読み取らないでください。ウインドウ単位の値については、iPhone Duo のサイズクラスを参照してください。
分割の方向を直接読み取ることもできます。splitArrangementAxis の環境値は、split の arrangement 内では .horizontal または .vertical、その外では nil になります。Apple の例では、これを使ってペイン内部のレイアウトを切り替えています。
struct DetailsView: View {
@Environment(\.splitArrangementAxis) var axis
var body: some View {
let layout: AnyLayout = axis == .horizontal
? AnyLayout(VStackLayout())
: AnyLayout(HStackLayout())
layout {
Artwork()
Metadata()
}
}
}
セカンダリビューが非表示になると、そのコントロールも一緒に消えます。フォーラムで Apple のエンジニアは、必須のビューに高い layoutPriority を与えて、そちらが残るようにすることを提案しています。その状態でもセカンダリのコンテンツにたどり着けるボタンやシートを用意するのもよいでしょう。
ArrangementView と NavigationSplitView はどう使い分ける?
この2つは異なる問題を解決するもので、入れ子にすることは想定されていません。
| NavigationSplitView | ArrangementView | |
|---|---|---|
| 保持するもの | ナビゲーションのカラム(サイドバー、コンテンツ、詳細) | 関連する2つのコンテンツビュー |
| ナビゲーション | あり。ナビゲーションコンテナそのもの | なし。ナビゲーションコンテナの中に置く |
| 外側ディスプレイでは | 1つのスタックに折りたたまれる | split は縦向きで上下に積み、横向きではプライマリのみ表示。overlay はビューを重ねる |
| 折り目では | 自動的に調整される | 各ビューをそれぞれの側に保つ |
| サイズの制御 | カラム幅 | 比率、サイズ、レイアウト優先度 |
メールの一覧と選択中のメールのように、ビューがナビゲーションの階層になっている場合は NavigationSplitView を使います。Apple のデザインガイダンスによると、split view は内側ディスプレイでは広がり、外側ディスプレイでは1つのペインに折りたたまれ、折り目に合わせて自動的に調整されます。アプリですでに使っているなら、ArrangementView はまったく必要ないかもしれません。
1つの遷移先の中で、同じ画面に存在する2つのビューには ArrangementView を使います。動画とそのコントロール、レシピとタイマー、ゲームの盤面とスコアカードなどがよく合います。Apple の iPhone Duo デザインガイダンスにあるパターンの1つがテーブルトップの姿勢です。離れて見るほうがよいコンテンツは立てた半分に、コントロールは平らに置いた半分に配置します。Built for the Fold ページに載っているようなゲームを見ると、このレイアウトがどれほど効果的かがわかります。
UIKit でも、UISplitViewController と UIArrangementViewController について同じアドバイスが当てはまります。フォーラムで Apple のエバンジェリストは、UIArrangementViewController の中に UINavigationController を埋め込むことは Apple として推奨していないと述べています。
まとめ:押さえておくべきポイントは?
- iOS 27.1 で追加された ArrangementView は、サイズクラス、アスペクト比、折り目を使ってプライマリとセカンダリのビューをレイアウトします。スタックとは違い、セカンダリビューを隠すことがあります。
- split は2つのビューを別々のスペースに保ち、分割できないときはプライマリだけを表示します。overlay はフラットなディスプレイでは2つを重ね、折り目では左右に分け、プライマリを trailing 側に置きます。
splitArrangementLayoutRatioはフラットなときのレイアウトを形作ります。Sarun の報告では、半開きの iPhone Duo では無視され、分割位置はヒンジ上になります。- 各ペインには独自のサイズクラスが与えられ、分割する軸は compact になります。環境は各ペインの内側で読み取ってください。
- ArrangementView はナビゲーションコンテナの中に置き、list、scroll view、NavigationSplitView の中には決して置かないでください。
次は、iPhone Duo のヒンジの状態と onHingeChange でヒンジそのものに反応する方法を学ぶか、iPhone Duo 対応準備チェックリストを進めてください。
よくある質問
SwiftUI の ArrangementView とは何ですか?
ArrangementView は iOS 27.1 で導入された SwiftUI のコンテナで、プライマリとセカンダリの2つのビューを保持します。サイズクラス、アスペクト比、そして iPhone Duo の折り目のような分割領域が有効かどうかを使って、各ビューを表示するかどうかと、どこに配置するかを決めます。
ArrangementView の split スタイルと overlay スタイルの違いは?
split スタイルは常に各ビューに専用のスペースを与え、左右または上下に並べます。分割できない場合はプライマリビューだけを表示します。overlay スタイルはフラットなディスプレイではプライマリビューをセカンダリビューの上に重ね、デバイスが部分的に折りたたまれると、2つを折り目の反対側に移します。
splitArrangementLayoutRatio は半開きの iPhone Duo でも効きますか?
iOS 開発者の Sarun Wongpatcharapakorn によると、効きません。半開きの iPhone Duo では比率が無視され、分割位置はヒンジ上で半分ずつになります。比率が適用されるのはディスプレイがフラットなときです。
ArrangementView の中に NavigationSplitView を入れるべきですか?
いいえ。Apple のドキュメントでは、arrangement view の中に navigation split view や tab view を入れること、また scroll view、list、navigation split view の中に arrangement view を入れることを避けるよう書かれています。代わりに NavigationStack などのナビゲーションコンテナの中に arrangement を置いてください。
ArrangementView の UIKit 版は何ですか?
UIKit では UIArrangementViewController を使います。Apple の iPhone Duo 向けアダプティブレイアウトの Tech Talk で示されているように、プライマリとセカンダリの配置にそれぞれビューコントローラを設定し、updateArrangement で配置を選びます。
出典
- Strike a pose with adaptive layouts on iPhone Duo (Tech Talk) · Apple Developer
- ArrangementView · Apple Developer Documentation
- splitArrangementLayoutRatio(_:) · Apple Developer Documentation
- SplitArrangementViewStyle · Apple Developer Documentation
- OverlayArrangementViewStyle · Apple Developer Documentation
- Prepare your app for iPhone Duo (Tech Talk) · Apple Developer
- Designing for iPhone Duo · Apple Human Interface Guidelines
- Designing for iPhone Duo · Blake Crosley
- How should ArrangementView behave across iPhone Duo display modes? · Apple Developer Forums
- Split style ArrangementView: side by side, or only the first view · @sarunw on X
- Overlay style ArrangementView: side by side in a fold, First View on the right · @sarunw on X
- splitArrangementLayoutRatio is ignored on a half-open iPhone Duo · @sarunw on X
- Size classes of each view in ArrangementView on iPhone Duo · @sarunw on X
折りたたみを、アプリの一部に。
AppleDuo は iPhone Duo を本当に活かしたアプリとゲームを紹介しています。App Store へのリンクを添えて送ってください。ほかの開発者の作品も見られます。