SwiftUIのListはセルの内部にButtonが配置されている場合、ButtonをタップしなくともセルをタップするだけでButtonのタップが誘発します。
セルの内部にButtonが複数配置されている場合、それぞれのButtonのアクションが実行されるためセルの内部にButtonを配置することが困難です。
代わりの手段としてタップしたい対象にはTapGestureを指定するのですが、ただ指定するだけだとタップしているようなエフェクトが出ないため視認性がよくありません。
ということで、Tapジェスチャにエフェクトをつけるスニペットを作ってみました。
struct TapGestureWithEffect: ViewModifier {
let action: () -> Void
@State private var opacity = 1.0
func body(content: Content) -> some View {
content
.opacity(self.opacity)
.gesture(TapGesture().onEnded {
withAnimation {
self.opacity = 0.3
}
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(150)) {
withAnimation {
self.opacity = 1
}
}
self.action()
})
}
}
これは以下のように利用出来ます。
struct ContentView: View {
var body: some View {
List {
ForEach(0..<100) { i in
HStack(spacing: 12) {
RoundedRectangle(cornerRadius: 5)
.fill(Color.black)
.frame(width: 50, height: 50)
Text("Action")
.modifier(TapGestureWithEffect {
print(i)
})
}
}
}
}
}
今回は単純にopacityを操作したエフェクトでしたが、このあたりを変更することでもう少しこだわったエフェクトを作ることも出来るかと思います。