Good day!
Question
How can we implement pinch gesture in SwiftUI and solve the gesture limitation from MagnificationGesture
Description
I'm trying to implement a pinch gesture recognizer on a scrollable LazyVGrid in a SwiftUI-based application, however the pinch gesture has usually been intercepted by the scroll gesture and makes it significantly harder to trigger than using UIKit's UIPinchGestureRecognizer. Here're my findings after a few tests.
MagnificationGesture: can detect the pinch gesture when two fingers are dragging at the same time.
UIPinchGestureRecognizer: can detect the pinch gesture when two fingers are touching and at least one finger is dragging.
Cases tried
ScrollView + LazyVGrid + MagnificationGesture
Result: difficult to trigger as described
ScrollView {
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3)) {
ForEach(aryItems) { item in
Text(item.photoId)
.border(Color.black, width: 1)
}
}
}
.highPriorityGesture(MagnificationGesture()
.onChanged { value in
print("test: \(value)")
})
ScrollView + LazyVGrid + .overlay() + UIPinchGestureRecognizer
Result: the pinch gesture is good, but the overlay blocked all gestures to the cells
(eg. tap, force-tap)
ScrollView {
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3)) {
ForEach(aryItems) { item in
Text(item.photoId)
.border(Color.black, width: 1)
}
}
.overlay (
GeometryReader{ proxy in
ZoomGesture(size: proxy.size,
onPinchUpdate: { scale, _ in
print("update pinch")
})
}
)
}
struct ZoomGesture: UIViewRepresentable {
var size: CGSize
var onPinchUpdate:((_ scale:CGFloat, _ position:CGPoint)->())? = { _,_ in }
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = .clear
let Pinchgesture = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handlePinch(sender:)))
view.addGestureRecognizer(Pinchgesture)
return view
}
func updateUIView(_ uiView: UIView, context: Context) { }
fileprivate class Coordinator: NSObject {
var parent: ZoomGesture
init(parent: ZoomGesture) {
self.parent = parent
}
@objc
func handlePinch(sender: UIPinchGestureRecognizer){
let scalePosition: CGPoint = .zero // temp
parent.onPinchUpdate?(sender.scale, scalePosition)
}
}
}
Thank you for your time!