Tomo.Log()


swiftUIでのViewのViewの表示・非表示について

[05/05, 2022]

日本語 / English

最近ようやくswiftUIを勉強し始めました、こんにちはトモです。

swiftUIは出てから3年目?に差し掛かろうとしていますが、まだまだ発展途上で仕様ややり方も大きく変わりそうなのですが、とりあえずswiftUIでのViewの表示・非表示についてのメモを残しておきます。

非表示には2通りの意味がある

1:非表示してViewのスペースは残す

Viewを非表示にするには、hidden()を呼ぶと、Viewが見えなくなります。また見えなくなってもView自体のスーペースは残ります。
opacity = 0 でも同じ感じのようです。

VStack {
   Text("text1")
   Text("text2").hidden() // text1とtext3の間にスペースが残ります。
   Text("text3")
}

2:非表示してViewのスペースは残さない(とるつめ)

AppleのドキュメントによるとViewのスペースを残さない場合(いわゆる、とるつめってやつですね)は、そもそもコードが実行されないようにしてくれみたいな感じでした。

VStack {
   Text("text1")
   if !isHidden {
      Text("text2") // text1とtext3の間にスペースが残らない
   }
   Text("text3")
}

ViewModifierで楽に制御する

このサイトにパターン1の場合の例が載っていたので参考にさせていただきました。

//パターン1の場合
struct VisibleModifier : ViewModifier {
    let visible:Bool    
    @ViewBuilder
    func body(content: Content) -> some View {
        if visible == false {
            content.hidden()
        } else {
            content
        }
    }
}

//パターン2の場合
struct HiddenModifier : ViewModifier {
    let hidden:Bool
    @ViewBuilder
    func body(content: Content) -> some View {
        if hidden {
            EmptyView()
        } else {
            content
        }
    }
}

extension View {
    func visible(_ visible:Bool) -> some View {
        modifier(VisibleModifier(visible: visible))
    }
    func hidden(_ hidden:Bool) -> some View {
        modifier(HiddenModifier(hidden: hidden))
    }
}

パターン1の場合はほぼコードそのまま使わせていただき、パターン2の場合どうすればいい感じにできるのかなーと思ったのですが、EmptyView()を返せばいいんじゃない?と思い、HiddenとVisibleの2つのModifierを用意して、extensionでラップして使いやすくしました。(このやり方もAppleのおすすめのやり方みたいですね)

Text("something").visible(flag) //見えなくなる&スペースはのこっる
Text("something").hidden(flag) //見えなくなる&スペースは残らない

こんな感じでswiftUIっぽくスッキリ描けるようになりました!😀 なんかswiftUIを勉強していて、swiftUIの考え方や概念って結構UIKitに持ち込めるんじゃないかなーとか、べつにUIKitを拡張してもいいなじゃないかなーと思うこともちょっとありますね。

とりあえず引き続き勉強していこうと思います。