[SwiftUI] sheetとfullScreenCoverを出したい

[SwiftUI] sheetとfullScreenCoverを出したい

Clock Icon2024.08.21

こんにちは。きんくまです。SwiftUI勉強中です。

モーダル遷移で別画面を表示したいです。

  • sheet: 画面の上がぴったり閉じず隙間が開く。下にスワイプすることで画面を閉じることが可能
  • fullScreenCover: 画面の上がぴったり隙間なく閉じる。下にスワイプしても画面は閉じられない

参考

Apple公式
Modal presentations

できたもの

https://www.youtube.com/shorts/-erZ5hKEq_Y

コード

ContentView


struct ContentView: View {
    @State private var isSheetPresenting = false
    @State private var isFullScreenCoverPresenting = false

    var body: some View {
        VStack {
            Spacer()

            Button {
                isSheetPresenting = true
            } label: {
                Text("Sheet")
            }
            .sheet(isPresented: $isSheetPresenting, onDismiss: didDismissSheet) {
                SecondView(isModalPresenting: $isSheetPresenting)
            }

            Spacer()

            Button {
                isFullScreenCoverPresenting = true
            } label: {
                Text("FullScreenCover")
            }
            .fullScreenCover(isPresented: $isFullScreenCoverPresenting, onDismiss: didDismissSheet) {
                SecondView(isModalPresenting: $isFullScreenCoverPresenting)
            }

            Spacer()
        }

    }

    func didDismissSheet() {
        print("Sheet dismissed \(isSheetPresenting)")
    }
}

開かれる方の画面です

SecondView


struct SecondView: View {
    @Binding var isModalPresenting:Bool

    var body: some View {
        VStack {
            Spacer()
            Text("Second View")
                .foregroundColor(Color.white)
            Spacer()
            Button {
                isModalPresenting = false
            } label: {
                Text("close")
                    .foregroundColor(Color.white)
            }
            Spacer()
        }
        .frame(maxWidth: .infinity,
            maxHeight: .infinity)
        .background(Color.blue)
    }
}

ここで、iOS 15からはdismissが追加されているのでSecondViewにEnvironmentプロパティを追加すれば親からのModal表示フラグを受け取らなくてもOK

dismiss

struct SecondView: View {
    // このプロパティは不要になる。親の方も修正する必要があるから今回は残している
    @Binding var isModalPresenting:Bool
    // ここです!
    @Environment(\.dismiss) private var dismiss: DismissAction

    var body: some View {
        VStack {
            Spacer()
            Text("Second View")
                .foregroundColor(Color.white)
            Spacer()
            Button {
                // ここです!
                dismiss()
            } label: {
                Text("close")
                    .foregroundColor(Color.white)
            }
            Spacer()
        }
        .frame(maxWidth: .infinity,
            maxHeight: .infinity)
        .background(Color.blue)
    }
}

そういやPreviewでBindingを設定するときに .constant でもできることを知った

#Preview {
    SecondView(isModalPresenting: .constant(true))
}

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.