##はじめに
SwiftUIではViewに対して.opacity(Double)で不透明度を指定することができます。
引数Doubleの値が0で透明、1で不透過、0.5では50%の透過度ということになります。
公式ドキュメント
https://developer.apple.com/documentation/swiftui/view/opacity(_:)
ただ、透明の時は、タップした時に動作させるonTapGestureが反応しなくなることを発見しました。
その存在が消されてしまうのでしょうか?
##検証
スライダーでサンプルを作成し実験してみました。
ボタンを押す男性をタップすると、上の表示がON/OFF切り替わるサンプルです。
このサンプルは次のような動きを示しました。
- opacityが0以外の時はON/OFFが切り替わる
- opacityが0の時はON/OFFが切り替わらない
以下、ソースコード
struct ContentView: View {
@State private var opacity: Double = 1.0
@State private var isOn: Bool = false
var body: some View {
VStack {
Spacer()
Text(isOn ? "ON" : "OFF")
.font(.title)
.fontWeight(.semibold)
.frame(width: 200, height: 100)
.background(isOn ? Color.red : Color.green)
.foregroundColor(isOn ? .white : .black)
Spacer()
Image("tapButtonImage")
.resizable()
.aspectRatio(contentMode: .fit)
.opacity(opacity)
.frame(width: 200)
.onTapGesture {
isOn.toggle()
}
Slider(value: $opacity)
Text("opacity: \(opacity)")
Spacer()
}
.padding()
}
}
opacityが0の時は、画像の存在そのものが消されている?とも考えましたが、画像が存在しなくなったら、スペースが詰められ、以下のような配置になるはずです。
なので枠として存在することになっています。
##タップ判定させたい場合
ちなみに、透明でもタップ判定できないかと調べていたところ、contentShapeを使うと反応することが分かりました。
以下、contentShapeを追加したコードです。
Image("tapButtonImage")
.resizable()
.aspectRatio(contentMode: .fit)
.opacity(opacity)
.frame(width: 200)
// contentShape追加
.contentShape(Rectangle())
.onTapGesture {
isOn.toggle()
}
こちらを参考にしました。
https://stackoverflow.com/questions/57258371/swiftui-increase-tap-drag-area-for-user-interaction
透明でもタップ判定させたい場合、contentShapeを使えば、願う動作を実装できます。
##おわりに
透明部分をタップして動作させたい!と思いopacityを0にしてコードを書いたのがこの現象に気づくきっかけでした。
引数を0.00001など限りなく0に近づければ、人間には透明に見えるが、機械からは透明ではないと判定されるので、問題ないっちゃ問題ないのですが。。
ですが、contentShapeという解決策も見つかったので、もし同じような現象で苦しんでいる方の参考になれば幸いです。
最後まで読んでくださりありがとうございました。