I have the following code:
struct ButtonTapTest: View {
let items = [1, 2, 3]
var body: some View {
List {
ForEach(items, id:.self) { item in
CellTestView()
}
}
}
}
struct CellTestView:View {
var body: some View {
VStack {
Button {
print("TOP")
} label: {
Image(systemName: "play.fill")
.font(.system(size: 40))
.foregroundColor(.red)
}
.border(.red)
Spacer()
Button {
print("BOTTOM")
} label: {
Image(systemName: "play")
.font(.system(size: 40))
.foregroundColor(.red)
}
.border(.yellow)
}
}
}
Creates the following screen:
Problem:
Both button actions get triggered in the cell regardless of where I tap on the CellTestView
. I want the individual button actions to trigger separately, each only when its button gets tapped, and not when I tap outside anywhere else on the cell.
You can see in the gif below that it does not matter where I tap on the CellTestView
, both button actions get trigger regardless where on the view I tap, and both "TOP" and "BOTTOM" logs trigger at the same time.
How can I fix this so the two buttons in the cell receive the tap independently and only when the tap is inside the related button?
3
Answers
My workaround for this problem is to wrap each button in its own VStack or HStack.
when you have a list, tapping on a list row will trigger both buttons.
Try this code to make each "button" equivalent, trigger separately.
Whenever you have multiple buttons in a list row, you need to manually set the button style to
.borderless
or.plain
. This is because buttons “adapt” to their context.According to the documentation:
So when your button is in a List, its tap target extends to fill the row and you get a highlight animation. SwiftUI isn’t smart enough to stop this side effect when you have more than 2 buttons, so you need to set
buttonStyle
manually.Result: