目次
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
コメント