ListlessiOS/Helpers/ItemRowDragGesture.swift (3234B)
1import SwiftUI
2
3extension View {
4 func itemDragGesture(
5 isActive: Bool,
6 itemID: UUID,
7 onDragStart: @escaping (CGFloat) -> Void,
8 onDragChanged: @escaping (CGPoint) -> Void,
9 onDragEnded: @escaping () -> Void
10 ) -> some View {
11 self.modifier(
12 ItemRowDragGesture(
13 isActive: isActive,
14 itemID: itemID,
15 onDragStart: onDragStart,
16 onDragChanged: onDragChanged,
17 onDragEnded: onDragEnded
18 ))
19 }
20}
21
22struct ItemRowDragGesture: ViewModifier {
23 let isActive: Bool
24 let itemID: UUID
25 let onDragStart: (CGFloat) -> Void
26 let onDragChanged: (CGPoint) -> Void
27 let onDragEnded: () -> Void
28
29 func body(content: Content) -> some View {
30 content
31 .gesture(
32 SimultaneousDragGesture(
33 isActive: isActive,
34 onDragStart: onDragStart,
35 onDragChanged: onDragChanged,
36 onDragEnded: onDragEnded
37 )
38 )
39 }
40}
41
42
43
44
45
46
47
48private struct SimultaneousDragGesture: UIGestureRecognizerRepresentable {
49 let isActive: Bool
50 let onDragStart: (CGFloat) -> Void
51 let onDragChanged: (CGPoint) -> Void
52 let onDragEnded: () -> Void
53
54 func makeUIGestureRecognizer(context: Context) -> UILongPressGestureRecognizer {
55 let recognizer = UILongPressGestureRecognizer()
56 recognizer.minimumPressDuration = 0.4
57 recognizer.delegate = context.coordinator
58 recognizer.isEnabled = isActive
59 return recognizer
60 }
61
62 func updateUIGestureRecognizer(_ recognizer: UILongPressGestureRecognizer, context: Context) {
63 recognizer.isEnabled = isActive
64 }
65
66 func handleUIGestureRecognizerAction(
67 _ recognizer: UILongPressGestureRecognizer, context: Context
68 ) {
69 switch recognizer.state {
70 case .began:
71 let width = recognizer.view?.bounds.width ?? 0
72 onDragStart(width)
73
74 case .changed:
75 let location = recognizer.location(in: recognizer.view?.window)
76 onDragChanged(location)
77
78 case .ended, .cancelled:
79 onDragEnded()
80
81 default:
82 break
83 }
84 }
85
86 func makeCoordinator(converter: CoordinateSpaceConverter) -> Coordinator {
87 Coordinator()
88 }
89
90 class Coordinator: NSObject, UIGestureRecognizerDelegate {
91 func gestureRecognizer(
92 _ gestureRecognizer: UIGestureRecognizer,
93 shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
94 ) -> Bool {
95 true
96 }
97
98 func gestureRecognizer(
99 _ gestureRecognizer: UIGestureRecognizer,
100 shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer
101 ) -> Bool {
102 otherGestureRecognizer.view is UITextView
103 }
104 }
105}