(2021/10/10 更新)
Viewをモーダル表示にするシート(sheet)の使い方を解説します。
完全な全画面表示ではなく、元の画面の上にカードをのせたようなイメージで、遷移元の画面が少し見えるのがシートの特徴です。
画面全体を覆うモーダルViewを表示したい場合は、sheetの代わりにfullScreenCoverを使用します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.5
【iOS】15.0
【macOS】Big Sur バージョン 11.6
基本的な使い方
SwiftUIは手続き型ではなく宣言型のコーディングスタイルですが、シートも例外ではありません。
その為、「シートを表示する」処理を書くのでは無く、次の.sheet()モディファイアでシート表示Viewの定義と表示する条件を設定します。
1 2 3 4 5 |
.sheet(isPresented: Binding<bool>) { // モーダル表示するViewを指定 } |
【引数】
isPresented
シートの表示可否を決める表示フラグ変数です。シートが閉じられると、表示フラグは自動的に false に戻ります。
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
struct ContentView: View { @State private var showingSheet = false var body: some View { Button("Sheetを開く") { self.showingSheet.toggle() } .sheet(isPresented: $showingSheet) { SecondView() } } } struct SecondView: View { var body: some View { Text("2番めのView") } } |
この例では、.sheet()モディファイアをButtonに定義していますが、実際はどこに定義されていても問題ありません。
.sheet()はButtonに連動するのではなく、あくまで表示フラグ(isPresented)に連動します。
.sheet()は階層的にも使えます。.sheet()で開いた画面からさらに別の画面が.sheet()で開けます。
画面を閉じる方法
.sheet()で表示した画面を閉じる方法には、次の3通りあります。
- 画面をスワイプで下げる。
- シートの表示フラグをfalseに書き換える。
- 環境変数で取得したdismissハンドラーを使用する。
ここでは、最後のdismissハンドラーを使用する例を紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
struct ContentView: View { @State private var showingSheet = false var body: some View { Button("Sheetを開く") { self.showingSheet.toggle() } .sheet(isPresented: $showingSheet) { SecondView() } } } struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { Button("画面を閉じる") { dismiss() } } } |
dismissハンドラーの詳細はこちらの記事を参照してください。
画面を閉じる時に実行する処理を指定
次のイニシャライザを使用して、画面を閉じる時に実行する処理を指定できます。
1 2 3 4 5 |
.sheet(isPresented: Binding<bool>, onDismiss: { シートを閉じる時に実行する処理 }) { // モーダル表示するViewを指定 } |
【引数】
onDismiss
シートが閉じる時に実行されるクロージャを指定します。
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
struct ContentView: View { @State private var showingSheet = false var body: some View { Button("Sheetを開く") { self.showingSheet.toggle() } .sheet(isPresented: $showingSheet, onDismiss: { print("シートを閉じた")} ) { SecondView() } } } struct SecondView: View { @Environment(\.dismiss) var dismiss var body: some View { Button("画面を閉じる") { dismiss() } } } |
尚、シートを閉じた時に実行する処理は、.onDisappear()モディファイアでも指定できますが、onDismissで指定する場合とはタイミングが異なります。
詳しくは、こちらの記事で解説しています。
シートにパラメータを渡す
シートにパラメータを渡してカスタマイズするには、次のイニシャライザを使用します。
1 2 3 4 5 6 7 8 9 |
.sheet(item: $item) { item in // モーダル表示するViewを指定 } .sheet(item: $item, onDismiss: { シートを閉じる時に実行する処理 }) { item in // モーダル表示するViewを指定 } |
【引数】
item
sheetに渡すパラメータを含んだオブジェクトのバインディングを指定します。
itemがnil以外の場合に、sheetが表示されます。
itemはIdentifiableに準拠する必要があります。
sheetが破棄された場合、itemは自動的に nil に戻されます。
itemが変更された場合は、sheetは一旦破棄され再描画されます。
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
struct UserInfo: Identifiable { let id = UUID() let name: String } struct ContentView: View { @State private var user: UserInfo? = nil var body: some View { VStack(spacing: 20) { Button("Apple") { user = UserInfo(name: "Apple") } Button("SwiftUI") { user = UserInfo(name: "SwiftUI") } } .sheet(item: $user) { item in NextView(user: item) } } } struct NextView: View { let user: UserInfo @Environment(\.dismiss) var dismiss var body: some View { VStack(spacing: 50) { Text("Hello \(user.name)!") .fontWeight(.heavy) .font(.title) Button("画面を閉じる") { dismiss() } } } } |