As the title says, when a ScrollView is near a UIViewControllerRepresentable, then the ScrollView's content no longer accurately recognizes taps. In particular, taps along the leading edge (10 points-ish) are ignored.
Here's a working example:
struct ContentView: View {
var body: some View {
HStack(spacing: 0) {
MyRepresentable()
// .allowsHitTesting(false)
ScrollView {
LazyVStack {
ForEach(0..<10, id: \.self) { index in
HStack(spacing: 0) {
Button {
print("tapped \(index)")
} label: {
Color.red
}
.frame(width: 50)
Color.blue
}
.frame(height: 50)
}
}
}
}
}
}
Here's the representable and a placeholder controller:
struct MyRepresentable: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MyViewController {
MyViewController()
}
func updateUIViewController(_ uiViewController: MyViewController, context: Context) {}
}
final class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
}
}
When you tap along the leading edge of the red buttons, the taps are ignored for about the first 10 points. But if you prevent hit testing on the representable (by un-commenting the .allowsHitTesting modifier), then the red buttons behave as expected. Also if you just remove the representable entirely, then all the buttons behave as expected.
It's as if the hit targets of the buttons are getting "pushed" over by the representable. Or is the representable simply intercepting these touches?
I've confirmed this incorrect behavior on iPad via touch and mouse. However, Apple Pencil (1st gen) and Apple Pencil Pro behave correctly - even in the presence of that UIViewControllerRepresentable. Perhaps the Pencil follows a different hit-test codepath?
Is this expected behavior? If so, then how do I use UIViewControllerRepresentable and ScrollView side-by-side?