はじめに
ビューを非表示にする方法はいくつかあり、どれを採用すればいいかの判断に迷うことがあったのでまとめました。
環境
- OS: macOS Sonoma 14.2.1 (23C71)
- Swift: 5.9.2
結論
先に結論です。
- トルツメ 1 →
ifやswitch - トルママ 2
- 常に非表示(レイアウトのためだけに配置する) →
hidden() - 条件によって表示/非表示を切り換える →
opacity(condition ? 1 : 0)
- 常に非表示(レイアウトのためだけに配置する) →
検証
簡単なコードで検証しました。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
Text("1")
if false {
Text("2") // 非表示
}
if true {
Text("3")
}
Text("4")
.hidden() // 非表示
Text("5")
.opacity(true ? 1: 0)
Text("6")
.opacity(true ? 0 : 1) // 非表示
Text("7")
}
}
}
上記のコードの実行結果です。
結論に記載した通り、 if で非表示にしたビューはトルツメされ、 hidden() や opacity() を付けて非表示にしたビューはトルママされました。
理由
このような結論を出した理由を記載します。
基本的にはすべて hidden() の公式ドキュメントに記載されている通りなので、ぜひご参照ください。
トルツメ
まずトルツメですが、モディファイアでは実現できなさそうなので if で行っています。
frame(height:) に 0 を指定することも思いつきましたが、非表示にはなりませんでした。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
Text("1")
.border(.red)
Text("2")
.frame(height: true ? 0 : 100)
.border(.green)
Text("3")
.border(.blue)
}
}
}
使える場面は限られますが、 let content: (() -> View)? のようにビューを返すオプショナルのクロージャを用意し、 content?() を実行してもトルツメが実現できます。
詳細は以下の記事をご参照ください。
トルママ
次にトルママですが、 hidden() のドキュメントに従っています。
ただ hidden() は表示/非表示を切り替えられないため、 opacity() を使うケースのほうが圧倒的に多いと思います。
私は hidden() を使ったことがありません。
opacity(0) のときはボタンをタップできないので、 hidden() と opacity(0) は同様の動作になると思います。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
Text("1")
Button {
print("Foo") // `opacity(0)` だとタップしても出力されない
} label: {
Text("2")
}
.opacity(0)
Text("3")
}
}
}
Button に対する opacity() の値をいろいろ変えて検証した結果をまとめました。
| opacity | 説明 |
|---|---|
1 |
少しでもボタンにかすればタップ判定になる |
0.9 〜 0.1
|
だんだんタップ領域が狭くなるが、タップがボタンの中央にかすればタップ判定になる |
0.01 |
かするだけではタップ判定にならない。タップの中心がボタンのフレームに入るとタップ判定になる |
0.001 〜 0
|
ボタンが完全に見えなくなり、タップもできなくなる |
透過度によってタップ領域が変わるのは学びでした。
おわりに
ビューを非表示にする方法の使い分けでした。
個人的には opacity() より hidden() のほうが非表示だとわかりやすいので、表示フラグを渡せる hidden() が欲しいです笑