7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【SwiftUI】opacityの謎

Last updated at Posted at 2021-01-24

##はじめに

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が切り替わらない
ezgif.com-video-to-gif.gif

以下、ソースコード

ContentView.swift
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の時は、画像の存在そのものが消されている?とも考えましたが、画像が存在しなくなったら、スペースが詰められ、以下のような配置になるはずです。
なので枠として存在することになっています。

スクリーンショット 2021-01-24 14.09.05.png   スクリーンショット 2021-01-24 14.33.38.png

##タップ判定させたい場合
ちなみに、透明でもタップ判定できないかと調べていたところ、contentShapeを使うと反応することが分かりました。
以下、contentShapeを追加したコードです。

ContentView.swift
Image("tapButtonImage")
  .resizable()
  .aspectRatio(contentMode: .fit)
  .opacity(opacity)
  .frame(width: 200)
  // contentShape追加
  .contentShape(Rectangle())
  .onTapGesture {
    isOn.toggle()
  }
ezgif.com-video-to-gif-3.gif

こちらを参考にしました。
https://stackoverflow.com/questions/57258371/swiftui-increase-tap-drag-area-for-user-interaction

透明でもタップ判定させたい場合、contentShapeを使えば、願う動作を実装できます。

##おわりに
透明部分をタップして動作させたい!と思いopacityを0にしてコードを書いたのがこの現象に気づくきっかけでした。
引数を0.00001など限りなく0に近づければ、人間には透明に見えるが、機械からは透明ではないと判定されるので、問題ないっちゃ問題ないのですが。。
ですが、contentShapeという解決策も見つかったので、もし同じような現象で苦しんでいる方の参考になれば幸いです。

最後まで読んでくださりありがとうございました。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?