MENU

【SwiftUI】超シンプル!モーダルの実装

    目次

    1. 閉じるボタン付きのモーダル実装

    概要

    @Bindingを用いる場合もありますが、ベストプラクティスとしては@Environmentを利用する実装方法です(iOS15以上が必要)。より簡略化してコードを書くことができます。
    注意点としては、@Binding同様に親子関係のViewになっている必要があります。

    実装例

    • 親View(モーダルの呼び出し元)
      モーダルを出すためには、.fullScreenCover(isPresented:){}を重ねる元の画面に設定します。読んで字の如く、「現在のスクリーンにフルカバーしますよ」といった具合です。
      .fullScreenCover(isPresented: $isShow){}の引数isPresentedのBoolで表示制御を実施します。$isShowは子View(ここではFullScreenで重なってくるModalView)にバインドさせるため、参照渡しをしています。これにより、親ビューと子ビュー相互に監視している状態を作ることができます。
    import SwiftUI
    
    struct BeforeModalView : View {
        @State var isShow = false
        var body: some View {
            Button(action: {
                isShow = true
            }, label: {
                Text("画面を表示")
                    .font(.largeTitle)
            })
            .fullScreenCover(isPresented: $isShow) {
                ModalView()
            }
        }
    }
    
    #if DEBUG
    struct BeforeModalView_Previews : PreviewProvider {
        static var previews: some View {
            BeforeModalView()
        }
    }
    #endif
    • 子View(モーダル画面)

    @Environment(\.isPresented) var isPresentedで自信が表示されているかいないかを知ることができます。
    @Environment(\.dismiss) var dismissを使用することで、dismiss()で自身のViewを閉じることができます。

    import SwiftUI
    
    struct ModalView : View {
        @Environment(\.isPresented) var isPresented
        @Environment(\.dismiss) var dismiss
        var body: some View {
        NavigationView {
            VStack {
                Text(isPresented ? "表示されている" : "非表示になった")
                    .font(.largeTitle)
                    .foregroundColor(.green)
                Button(action: {
                    dismiss()
                }, label: {
                    Text("閉じる")
                        .font(.largeTitle)
                })
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(.pink)
            }
        }
    }
    
    #if DEBUG
    struct ModalView_Previews : PreviewProvider {
        static var previews: some View {
            BeforeModalView()
            ModalView()
        }
    }
    #endif

    2. モーダルのカスタム

    概要

    1の例では、標準的なモーダルを作成しました。ここでは、NavigationViewと組み合わせて、よくアプリで使用されているモーダルに改造します。
    モーダル左上にXボタンを設置して、Xを押すとモーダルが破棄されるように実装します。

    実装例

    .navigationBarItemsを使用することで好きな場所にナビゲーションバーアイテムを置くことができます。

    .navigationBarItems(leading: 左側のView)
    .navigationBarItems(trailing: 右側のView)
    .navigationBarItems(leading: 左側のView, trailing: 右側のView)

    早速上記を活用して、左上にCancelボタンを設置したモーダルを実装します。

    struct ModalView : View {
        @Environment(\.isPresented) var isPresented
        @Environment(\.dismiss) var dismiss
        var body: some View {
            NavigationView {
                VStack {
                    Text(isPresented ? "表示されている" : "非表示になった")
                        .font(.largeTitle)
                        .foregroundColor(.green)
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(.pink)
                .navigationBarItems(leading:
                                        Button(action: {
                        dismiss()
                }) {
                    Text("Cancel")
                })
            }
    
        }
    }
    
    #if DEBUG
    struct ModalView_Previews : PreviewProvider {
        static var previews: some View {
            BeforeModalView()
            ModalView()
        }
    }
    #endif
    よかったらシェアしてね!
    • URLをコピーしました!
    • URLをコピーしました!

    この記事を書いた人

    Rio@iOSエンジニアのアバター Rio@iOSエンジニア 経営者兼モバイルアプリエンジニア

    都内のモバイルアプリ開発会社経営者。
    モバイルアプリの新規の請負開発及び保守運用を引き受ける。
    Denso→Honda→現在
    #RxSwift #MVVM #Firebase #Python3

    コメント

    コメントする

    目次