【SwiftUI】フルスクリーンでモーダル表示する【fullScreenCover】

モーダルで View を表示する場合、iOS13 の SwiftUI では sheet による表示方法のみでした。今回は iOS14 から導入された全画面表示fullScreenCover について解説します。

フルスクリーンでモーダル表示する

先ず、sheet による表示方法をおさらいします。

@State private var isShowing = false

Button("タップしてモーダル表示") {
    isShowing = true
}
.sheet(isPresented: $isShowing) {
    ModalView()
}

.sheet では画面下から登場し、呼び出し元の画面の約8割ほどを覆い被さるような感じに表示され、下方向にスワイプすることで捌けさせることができました。

fullScreenCover も基本的には sheet と同じです。

@State private var isShowing = false

Button("タップしてフルスクリーン表示") {
    isShowing = true
}
.fullScreenCover(isPresented: $isShowing) {
    ModalView()
}

メソッド名が変わっただけで引数も同じです。

ただし、このままだと問題があります。sheet と違って、fullScreenCover ではスワイプで捌けさせることができないため、表示トリガーである @State 変数(ここでは isShowing)を false に戻さないと元の画面に戻れなくなってしまいます

以下の例のように対応することでモーダルを閉じることができます(冒頭のサンプル動画のコードです)。

struct ContentView: View {
    
    @State private var isShowing = false
    
    var body: some View {
        Button("Show Modal") {
            isShowing = true
        }
        .fullScreenCover(isPresented: $isShowing) {
            ModalView(isActive: $isShowing)
        }
    }
}

struct ModalView: View {

    @Binding var isActive: Bool
    
    var body: some View {
        HStack {
            Spacer()
            VStack {
                Spacer()
                Text("Modal View").padding()
                Button("Close Modal") {
                    isActive = false
                }
                Spacer()
            }
            Spacer()
        }
        .padding()
        .background(Color(.yellow))
    }
}

isShowingModalView の引数として渡し、isActive にバインディングさせ、ModalView 側で false にしています。

自分で閉じるロジックを組み込まないといけないところは面倒ですが、スワイプで勝手に閉じられるとまずい仕様などの場合に fullScreenCover を使うと良いでしょう。

以上