今回は、SwiftUIでハーフモーダルビューの作り方に関して紹介したいと思います。
動作
「モーダルを表示」ボタンを押下→モーダル表示
「閉じる」or再度「モーダルを表示」を押下→モーダル非表示
の切り替えを行なっています。
プログラム
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var screenHeight: CGFloat = 0.0
@State private var showHalfModal = false
var body: some View {
GeometryReader(content: { geometry in
ZStack{
Button(action: {
self.showHalfModal.toggle()
}, label: {
Text("モーダルを表示")
.font(.largeTitle)
})
HalfModal(closedButton: $showHalfModal,
sizeY: screenHeight,
objectHeight: 400.0)
}
.onAppear(perform: {
screenHeight = geometry.size.height // スクリーンサイズ(縦幅)を取得
})
})
.ignoresSafeArea(.all) // 上下のセーフエリアを無効化
}
}
struct HalfModal: View {
@Binding var closedButton: Bool
let sizeY: CGFloat
let objectHeight: CGFloat
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 50.0)
.foregroundColor(.red)
VStack {
Spacer()
Button(action: {
closedButton.toggle()
}, label: {
Text("閉じる")
.foregroundColor(.white)
.font(.largeTitle)
})
Spacer()
}
}
.frame(height: objectHeight)
.offset(y: closedButton ? sizeY-objectHeight : sizeY)
}
}
プログラムの説明
GeometryReaderで画面サイズ取得
.ignoresSafeArea(.all)
でContentViewのSafeAreaを無効化、geometry.size.height
で画面全体の縦幅を取得し、screenHeight
変数に代入します。
ZStackで同時に表示
ContentView
とHalfModal
をZStackで囲むことによって、一つの画面内に2つのViewコンポーネントを表示します。そして、HalfModal側でoffset()
(表示位置の移動)を宣言することで、画面下部にハーフモーダルが表示されるようになります。
offsetで表示位置を変更
Swiftは真偽値で処理を分岐できる
[Bool] ? [trueの処理]:[falseの処理]
といった処理を書くことができます。
ですから、
- true:y座標を「全体の縦幅」の位置に表示
- false:y座標を「全体の縦幅」-「モーダルの縦幅」の位置に表示
と指定してあげればアクションを起こす(=Bool値を変更する)と他のViewが表示される処理を実装することができます。
ソースコード
GitHub上で公開していますので、参考程度にどうぞ。