はじめに
バックグラウンドで何か重たい処理をしていて、処理が終わるまで待機する必要があるときに、インジケータダイアログを出しておくことがあると思います。併せて背景をぼやかして、ちょっとオサレに見せたい時のお話。
例えば、SVProgressHUDのようなイメージです。
ActivityIndicatorを出すまえに、まずは背景をぼやかすところで少し実験をしてみました。
ZStackでぼやかしたViewをかぶせる
方針
まずは安直パターン。ZStackであらかじめ重ねておいて、表示非表示を切り替えます。
ぼやかしたViewを重ねて、下にあるView群がぼやけるかどうかがポイントになります。
コード
ぼやけたViewを用意します。
struct BlurViewV1: View {
@Binding var isShowing:Bool
var body: some View {
Rectangle()
.fill(Color.gray)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.opacity(0.6)
.blur(radius: 3.0)
.blendMode(.normal)
.opacity(self.isShowing ? 1.0:0.0)
}
}
ぼやけたViewを重ねて表示しておきます。もちろん初期状態は非表示で。
struct ContentView: View {
@State var isShowing:Bool = false
var body: some View {
// V1
ZStack {
VStack {
Text("Hello, World!")
.font(.largeTitle)
Button(action: {
self.isShowing = true
self.blur()
}) {
Text("Blur!")
}
}
BlurViewV1(isShowing: self.$isShowing)
}
}
ボタンをタップするとぼやけたViewが表示されます。self.blur()
では2秒待って非表示に戻す処理を行っています。
どのように表示されるか
さて、うまくいきますかどうか。
あれ?確かに重なっていますが、ぼやけていないぞ? Hello,World!がはっきり見えています。
ぼやかすモディファイアを付加したViewに、ぼやかしたいViewをプロパティとして保持する
方針
ややこしい言い回しですが、要するにぼやかして表示したいViewのblurモディファイアを使ってぼやかす方法です。
コード
struct BlurViewV2<Content>: View where Content: View {
@Binding var isShowing:Bool
var content: () -> Content
var body: some View {
ZStack {
content()
.blur(radius: isShowing ? 3.0 : 0.0)
Rectangle()
.fill(Color.gray)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.opacity(0.6)
.blur(radius: 3.0)
.blendMode(.normal)
.opacity(self.isShowing ? 1.0:0.0)
}
}
ぼやかしたViewをかぶせる時と対比するために、あえてコードをそのまま流用しています。
Viewプロトコルに準拠したジェネリクス型を定義しておき、任意のViewをプロパティとして保持できるようにしています。
ぼやかしたViewをかぶせる時と同様にコーディングしていきます。
struct ContentView: View {
@State var isShowing:Bool = false
var body: some View {
// V2
BlurViewV2(isShowing: self.$isShowing) {
VStack {
Text("Hello, World!")
.font(.largeTitle)
Button(action: {
self.isShowing = true
self.blur()
}) {
Text("Blur!")
}
}
}
}
どのように表示されるか
今度はどうでしょう?
良き感じにぼやけています。
まとめ
ぼやけたViewをかぶせる安直な方法はお手軽に実装できます。しかしながら、ぼかしまではかぶせたViewには適用されなかった……
すりガラスを通して見るような感じを想定していたんですけどね。
かぶせる方式は重たい処理をしているときに待機させるときに使うというよりも、純粋にボタンなどを操作させないようにするときに使うのが良いかもしれません。ただし、操作できそうに見えて操作できないようにしてしまうため、使い所に注意が必要かもしれません。