I am attempting to attach a modifier to a ScrollView that still allows scrolling and disables all the underlying buttons:
struct ContentView1: View {
var body: some View {
ScrollViewButtonDisableView()
.modifier(ScrollHitModifier())
}
}
struct ScrollViewButtonDisableView: View {
var body: some View {
ScrollView {
VStack {
ForEach(0...100, id: \.self) { buttonNumber in
Button("Press \(buttonNumber)") {
print("Button number \(buttonNumber) pressed")
}
.buttonStyle(.borderedProminent)
.font(.title)
.padding()
}
}
}
}
}
struct ScrollHitModifier: ViewModifier {
func body(content: Content) -> some View {
content
.allowsHitTesting(false)
}
}
Unfortunately the result is that both the buttons and the scrolling do not work any more. I still want to be able to scroll.
I know that I can add the modifier ScrollHitModifier() to the VStack in ScrollViewButtonDisableView, but that defeats the purpose of what I am looking for. I would like to add a modifier to the overall struct and not have to place it into the struct.
Is there any way to attach an .allowsHitTesting
modifier to the ScrollViewButtonDisableView and still allow scrolling?
You could add a dummy TapGesture
as a .highPriorityGesture
to the ScrollView
. This blocks tap gestures on the content inside the ScrollView
, but still allows scrolling to be performed.
EDIT Adding .including: .gesture
seems to help to prevent gestures from reaching the subviews (ref. comments). The documentation for this GestureMask
states:
Enable the added gesture but disable all gestures in the subview hierarchy.
...which is just what's needed!
struct ScrollHitModifier: ViewModifier {
func body(content: Content) -> some View {
content
.highPriorityGesture(
TapGesture(),
including: .gesture
)
}
}