【Swift UI】カスタムアラートダイアログの実装方法!ViewBuilder
この記事からわかること
- Swift UIでカスタムアラートダイアログを実装するには?
- ViewBuilderの使い方
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.1
- Swift:5.9
- macOS:Sonoma 14.1
Swift UIでカスタムダイアログの実装方法
Swift UIを使用してデフォルトで出せる以下のようなデザインのアラートではなく、自分でデザインを変更できるアラートダイアログを実装する方法をまとめていきます。
実装方法は@ViewBuilder
を使用してCustomDialog
ビューを構築し、ZStackで対象の画面に重ねるだけです。
struct CustomDialog<Content: View>: View {
var content: Content
@State private var isShow = true
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content()
}
var body: some View {
if isShow {
ZStack {
// 画面全体を覆う黒い背景
Color.black
.opacity(0.5)
.onTapGesture {
isShow = false
}
// ダイアログコンテンツ部分
content
// 画面一杯にViewを広げる
}.ignoresSafeArea()
}
}
}
この実装ではカスタムダイアログのデザインを毎回呼び出し側から変更できるように実装しています。
struct ContentView: View {
var body: some View {
ZStack {
Text("Main View")
CustomDialog {
VStack {
Text("カスタムダイアログ")
.frame(width: 200)
.padding()
.background(.black)
.foregroundStyle(.white)
.fontWeight(.bold)
Spacer()
Text("TextTextTextTextTextTextTextTextTextTextText")
Spacer()
}.frame(width: 200, height: 150)
.background(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
}
}
呼び出す側と変数を共有したい場合
ダイアログを呼び出す側と変数を共有し、呼び出す側に表示/非表示フラグを持たせたい場合は@Binding
を使用すれば実装することが可能です。
struct CustomDialog<Content: View>: View {
var content: Content
@Binding var isShow: Bool
init(isShow: Binding<Bool>, @ViewBuilder content: @escaping () -> Content) {
self._isShow = isShow
self.content = content()
}
var body: some View {
ZStack {
Color.black
.opacity(0.5)
.onTapGesture {
isShow = false
}
content
}.ignoresSafeArea()
}
}
呼び出し側はこのような感じになります。
struct ContentView: View {
@State var isShow: Bool = true
var body: some View {
ZStack {
Text("Main View")
if isShow {
CustomDialog(isShow: $isShow) {
VStack {
Text("カスタムダイアログ")
.frame(width: 200)
.padding()
.background(.black)
.foregroundStyle(.white)
.fontWeight(.bold)
Spacer()
Text("TextTextTextTextTextTextTextTextTextTextText")
Spacer()
}.frame(width: 200, height: 150)
.background(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
}
}
}
ご覧いただきありがとうございました。