react-native-gesture-handler 2.19.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +7 -12
- package/android/fabric/src/main/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +1 -1
- package/android/paper/src/main/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +1 -1
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureUtils.kt +1 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt +11 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +8 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/StylusData.kt +103 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +24 -15
- package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/HoverGestureHandlerEventDataBuilder.kt +7 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/PanGestureHandlerEventDataBuilder.kt +7 -0
- package/android/src/main/jni/CMakeLists.txt +18 -9
- package/apple/Handlers/RNLongPressHandler.m +2 -0
- package/apple/Handlers/RNPanHandler.m +57 -7
- package/apple/Handlers/RNRotationHandler.m +1 -1
- package/apple/RNGHStylusData.h +77 -0
- package/apple/RNGHStylusData.m +37 -0
- package/apple/RNGestureHandlerButtonComponentView.mm +35 -0
- package/apple/RNGestureHandlerEvents.h +3 -1
- package/apple/RNGestureHandlerEvents.m +11 -3
- package/lib/commonjs/components/GestureButtons.js +5 -1
- package/lib/commonjs/components/GestureButtons.js.map +1 -1
- package/lib/commonjs/components/GestureComponents.js.map +1 -1
- package/lib/commonjs/components/Pressable/Pressable.js +5 -14
- package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
- package/lib/commonjs/components/Pressable/utils.js +1 -23
- package/lib/commonjs/components/Pressable/utils.js.map +1 -1
- package/lib/commonjs/handlers/GestureHandlerEventPayload.js +4 -0
- package/lib/commonjs/handlers/createHandler.js +2 -1
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
- package/lib/commonjs/handlers/gestures/hoverGesture.js.map +1 -1
- package/lib/commonjs/jestUtils/jestUtils.js +12 -4
- package/lib/commonjs/jestUtils/jestUtils.js.map +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js +1 -3
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/HoverGestureHandler.js +18 -1
- package/lib/commonjs/web/handlers/HoverGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js +8 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/commonjs/web/interfaces.js.map +1 -1
- package/lib/commonjs/web/tools/EventManager.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +0 -3
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/commonjs/web/tools/PointerEventManager.js +3 -37
- package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -1
- package/lib/commonjs/web/utils.js +173 -0
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/components/GestureButtons.js +5 -1
- package/lib/module/components/GestureButtons.js.map +1 -1
- package/lib/module/components/GestureComponents.js.map +1 -1
- package/lib/module/components/Pressable/Pressable.js +7 -14
- package/lib/module/components/Pressable/Pressable.js.map +1 -1
- package/lib/module/components/Pressable/utils.js +1 -22
- package/lib/module/components/Pressable/utils.js.map +1 -1
- package/lib/module/handlers/GestureHandlerEventPayload.js +1 -1
- package/lib/module/handlers/createHandler.js +2 -1
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/handlers/gestures/gesture.js.map +1 -1
- package/lib/module/handlers/gestures/hoverGesture.js.map +1 -1
- package/lib/module/jestUtils/jestUtils.js +12 -4
- package/lib/module/jestUtils/jestUtils.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +1 -3
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/handlers/HoverGestureHandler.js +18 -1
- package/lib/module/web/handlers/HoverGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PanGestureHandler.js +8 -1
- package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/module/web/interfaces.js.map +1 -1
- package/lib/module/web/tools/EventManager.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js +0 -2
- package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/module/web/tools/PointerEventManager.js +4 -38
- package/lib/module/web/tools/PointerEventManager.js.map +1 -1
- package/lib/module/web/utils.js +170 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/components/GestureComponents.d.ts +1 -1
- package/lib/typescript/components/Pressable/utils.d.ts +3 -5
- package/lib/typescript/handlers/GestureHandlerEventPayload.d.ts +35 -0
- package/lib/typescript/handlers/gestures/gesture.d.ts +2 -2
- package/lib/typescript/handlers/gestures/hoverGesture.d.ts +1 -6
- package/lib/typescript/handlers/handlersRegistry.d.ts +1 -1
- package/lib/typescript/jestUtils/jestUtils.d.ts +1 -1
- package/lib/typescript/web/handlers/HoverGestureHandler.d.ts +2 -0
- package/lib/typescript/web/handlers/PanGestureHandler.d.ts +3 -1
- package/lib/typescript/web/interfaces.d.ts +8 -3
- package/lib/typescript/web/tools/EventManager.d.ts +2 -2
- package/lib/typescript/web/utils.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/GestureButtons.tsx +2 -1
- package/src/components/GestureComponents.tsx +1 -1
- package/src/components/Pressable/Pressable.tsx +16 -29
- package/src/components/Pressable/utils.ts +5 -49
- package/src/handlers/GestureHandlerEventPayload.ts +42 -0
- package/src/handlers/createHandler.tsx +1 -0
- package/src/handlers/gestures/gesture.ts +3 -1
- package/src/handlers/gestures/hoverGesture.ts +1 -7
- package/src/jestUtils/jestUtils.ts +9 -1
- package/src/web/handlers/GestureHandler.ts +1 -1
- package/src/web/handlers/HoverGestureHandler.ts +16 -2
- package/src/web/handlers/PanGestureHandler.ts +10 -1
- package/src/web/interfaces.ts +9 -3
- package/src/web/tools/EventManager.ts +2 -4
- package/src/web/tools/GestureHandlerWebDelegate.ts +0 -2
- package/src/web/tools/PointerEventManager.ts +2 -38
- package/src/web/utils.ts +174 -1
- package/lib/commonjs/web/tools/TouchEventManager.js +0 -164
- package/lib/commonjs/web/tools/TouchEventManager.js.map +0 -1
- package/lib/module/web/tools/TouchEventManager.js +0 -149
- package/lib/module/web/tools/TouchEventManager.js.map +0 -1
- package/lib/typescript/web/tools/TouchEventManager.d.ts +0 -11
- package/src/web/tools/TouchEventManager.ts +0 -175
package/android/build.gradle
CHANGED
|
@@ -33,16 +33,10 @@ def resolveReactNativeDirectory() {
|
|
|
33
33
|
return file(reactNativeLocation)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return reactNativeFromProjectNodeModules
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
def reactNativeFromNodeModulesWithReanimated = file("${projectDir}/../../react-native")
|
|
44
|
-
if (reactNativeFromNodeModulesWithReanimated.exists()) {
|
|
45
|
-
return reactNativeFromNodeModulesWithReanimated
|
|
36
|
+
// Fallback to node resolver for custom directory structures like monorepos.
|
|
37
|
+
def reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
|
|
38
|
+
if (reactNativePackage.exists()) {
|
|
39
|
+
return reactNativePackage.parentFile
|
|
46
40
|
}
|
|
47
41
|
|
|
48
42
|
throw new Exception(
|
|
@@ -124,8 +118,7 @@ android {
|
|
|
124
118
|
externalNativeBuild {
|
|
125
119
|
cmake {
|
|
126
120
|
cppFlags "-O2", "-frtti", "-fexceptions", "-Wall", "-Werror", "-std=c++20", "-DANDROID"
|
|
127
|
-
arguments "-
|
|
128
|
-
"-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}",
|
|
121
|
+
arguments "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}",
|
|
129
122
|
"-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
|
|
130
123
|
"-DANDROID_STL=c++_shared"
|
|
131
124
|
abiFilters (*reactNativeArchitectures())
|
|
@@ -153,6 +146,8 @@ android {
|
|
|
153
146
|
// only the ones that make the build fail (ideally we should only include libgesturehandler but we
|
|
154
147
|
// are only allowed to specify exclude patterns)
|
|
155
148
|
exclude "**/libreact_render*.so"
|
|
149
|
+
exclude "**/libreactnative.so"
|
|
150
|
+
exclude "**/libjsi.so"
|
|
156
151
|
}
|
|
157
152
|
|
|
158
153
|
sourceSets.main {
|
|
@@ -8,5 +8,5 @@ import com.facebook.react.uimanager.events.Event
|
|
|
8
8
|
|
|
9
9
|
fun ReactContext.dispatchEvent(event: Event<*>) {
|
|
10
10
|
val fabricUIManager = UIManagerHelper.getUIManager(this, UIManagerType.FABRIC) as FabricUIManager
|
|
11
|
-
fabricUIManager.
|
|
11
|
+
fabricUIManager.getEventDispatcher().dispatchEvent(event)
|
|
12
12
|
}
|
|
@@ -6,7 +6,7 @@ import com.facebook.react.uimanager.events.Event
|
|
|
6
6
|
|
|
7
7
|
fun ReactContext.dispatchEvent(event: Event<*>) {
|
|
8
8
|
try {
|
|
9
|
-
this.getNativeModule(UIManagerModule::class.java)!!.
|
|
9
|
+
this.getNativeModule(UIManagerModule::class.java)!!.getEventDispatcher().dispatchEvent(event)
|
|
10
10
|
} catch (e: NullPointerException) {
|
|
11
11
|
throw Exception("Couldn't get an instance of UIManagerModule. Gesture Handler is unable to send an event.", e)
|
|
12
12
|
}
|
|
@@ -11,6 +11,8 @@ import com.swmansion.gesturehandler.react.RNViewConfigurationHelper
|
|
|
11
11
|
class HoverGestureHandler : GestureHandler<HoverGestureHandler>() {
|
|
12
12
|
private var handler: Handler? = null
|
|
13
13
|
private var finishRunnable = Runnable { finish() }
|
|
14
|
+
var stylusData: StylusData = StylusData()
|
|
15
|
+
private set
|
|
14
16
|
|
|
15
17
|
private infix fun isAncestorOf(other: GestureHandler<*>): Boolean {
|
|
16
18
|
var current: View? = other.view
|
|
@@ -103,6 +105,10 @@ class HoverGestureHandler : GestureHandler<HoverGestureHandler>() {
|
|
|
103
105
|
finish()
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
this.state == STATE_ACTIVE && event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS -> {
|
|
109
|
+
stylusData = StylusData.fromEvent(event)
|
|
110
|
+
}
|
|
111
|
+
|
|
106
112
|
this.state == STATE_UNDETERMINED &&
|
|
107
113
|
(event.action == MotionEvent.ACTION_HOVER_MOVE || event.action == MotionEvent.ACTION_HOVER_ENTER) -> {
|
|
108
114
|
begin()
|
|
@@ -111,6 +117,11 @@ class HoverGestureHandler : GestureHandler<HoverGestureHandler>() {
|
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
|
|
120
|
+
override fun onReset() {
|
|
121
|
+
super.onReset()
|
|
122
|
+
stylusData = StylusData()
|
|
123
|
+
}
|
|
124
|
+
|
|
114
125
|
private fun finish() {
|
|
115
126
|
when (this.state) {
|
|
116
127
|
STATE_UNDETERMINED -> cancel()
|
|
@@ -45,6 +45,8 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
|
|
|
45
45
|
private var activateAfterLongPress = DEFAULT_ACTIVATE_AFTER_LONG_PRESS
|
|
46
46
|
private val activateDelayed = Runnable { activate() }
|
|
47
47
|
private var handler: Handler? = null
|
|
48
|
+
var stylusData: StylusData = StylusData()
|
|
49
|
+
private set
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
52
|
* On Android when there are multiple pointers on the screen pan gestures most often just consider
|
|
@@ -212,6 +214,10 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
|
|
|
212
214
|
return
|
|
213
215
|
}
|
|
214
216
|
|
|
217
|
+
if (event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) {
|
|
218
|
+
stylusData = StylusData.fromEvent(event)
|
|
219
|
+
}
|
|
220
|
+
|
|
215
221
|
val state = state
|
|
216
222
|
val action = sourceEvent.actionMasked
|
|
217
223
|
if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
|
|
@@ -295,6 +301,8 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
|
|
|
295
301
|
it.recycle()
|
|
296
302
|
velocityTracker = null
|
|
297
303
|
}
|
|
304
|
+
|
|
305
|
+
stylusData = StylusData()
|
|
298
306
|
}
|
|
299
307
|
|
|
300
308
|
override fun resetProgress() {
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
package com.swmansion.gesturehandler.core
|
|
2
|
+
|
|
3
|
+
import android.view.MotionEvent
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import kotlin.math.PI
|
|
7
|
+
import kotlin.math.abs
|
|
8
|
+
import kotlin.math.atan
|
|
9
|
+
import kotlin.math.cos
|
|
10
|
+
import kotlin.math.round
|
|
11
|
+
import kotlin.math.sin
|
|
12
|
+
import kotlin.math.tan
|
|
13
|
+
|
|
14
|
+
data class StylusData(
|
|
15
|
+
val tiltX: Double = 0.0,
|
|
16
|
+
val tiltY: Double = 0.0,
|
|
17
|
+
val altitudeAngle: Double = 0.0,
|
|
18
|
+
val azimuthAngle: Double = 0.0,
|
|
19
|
+
val pressure: Double = -1.0
|
|
20
|
+
) {
|
|
21
|
+
fun toReadableMap(): ReadableMap {
|
|
22
|
+
val stylusDataObject = Arguments.createMap().apply {
|
|
23
|
+
putDouble("tiltX", tiltX)
|
|
24
|
+
putDouble("tiltY", tiltY)
|
|
25
|
+
putDouble("altitudeAngle", altitudeAngle)
|
|
26
|
+
putDouble("azimuthAngle", azimuthAngle)
|
|
27
|
+
putDouble("pressure", pressure)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
val readableStylusData: ReadableMap = stylusDataObject
|
|
31
|
+
|
|
32
|
+
return readableStylusData
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
companion object {
|
|
36
|
+
// Source: https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
|
|
37
|
+
private fun spherical2tilt(altitudeAngle: Double, azimuthAngle: Double): Pair<Double, Double> {
|
|
38
|
+
val eps = 0.000000001
|
|
39
|
+
val radToDeg = 180 / PI
|
|
40
|
+
|
|
41
|
+
var tiltXrad = 0.0
|
|
42
|
+
var tiltYrad = 0.0
|
|
43
|
+
|
|
44
|
+
if (altitudeAngle < eps) {
|
|
45
|
+
// the pen is in the X-Y plane
|
|
46
|
+
if (azimuthAngle < eps || abs(azimuthAngle - 2 * PI) < eps) {
|
|
47
|
+
// pen is on positive X axis
|
|
48
|
+
tiltXrad = PI / 2
|
|
49
|
+
}
|
|
50
|
+
if (abs(azimuthAngle - PI / 2) < eps) {
|
|
51
|
+
// pen is on positive Y axis
|
|
52
|
+
tiltYrad = PI / 2
|
|
53
|
+
}
|
|
54
|
+
if (abs(azimuthAngle - PI) < eps) {
|
|
55
|
+
// pen is on negative X axis
|
|
56
|
+
tiltXrad = -PI / 2
|
|
57
|
+
}
|
|
58
|
+
if (abs(azimuthAngle - (3 * PI) / 2) < eps) {
|
|
59
|
+
// pen is on negative Y axis
|
|
60
|
+
tiltYrad = -PI / 2
|
|
61
|
+
}
|
|
62
|
+
if (azimuthAngle > eps && abs(azimuthAngle - PI / 2) < eps) {
|
|
63
|
+
tiltXrad = PI / 2
|
|
64
|
+
tiltYrad = PI / 2
|
|
65
|
+
}
|
|
66
|
+
if (abs(azimuthAngle - PI / 2) > eps && abs(azimuthAngle - PI) < eps) {
|
|
67
|
+
tiltXrad = -PI / 2
|
|
68
|
+
tiltYrad = PI / 2
|
|
69
|
+
}
|
|
70
|
+
if (abs(azimuthAngle - PI) > eps && abs(azimuthAngle - (3 * PI) / 2) < eps) {
|
|
71
|
+
tiltXrad = -PI / 2
|
|
72
|
+
tiltYrad = -PI / 2
|
|
73
|
+
}
|
|
74
|
+
if (abs(azimuthAngle - (3 * PI) / 2) > eps && abs(azimuthAngle - 2 * PI) < eps) {
|
|
75
|
+
tiltXrad = PI / 2
|
|
76
|
+
tiltYrad = -PI / 2
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
val tanAlt = tan(altitudeAngle)
|
|
80
|
+
|
|
81
|
+
tiltXrad = atan(cos(azimuthAngle) / tanAlt)
|
|
82
|
+
tiltYrad = atan(sin(azimuthAngle) / tanAlt)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
val tiltX = round(tiltXrad * radToDeg)
|
|
86
|
+
val tiltY = round(tiltYrad * radToDeg)
|
|
87
|
+
|
|
88
|
+
return Pair(tiltX, tiltY)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fun fromEvent(event: MotionEvent): StylusData {
|
|
92
|
+
// On web and iOS 0 degrees means that stylus is parallel to the surface. On android this value will be PI / 2.
|
|
93
|
+
val altitudeAngle = (PI / 2) - event.getAxisValue(MotionEvent.AXIS_TILT).toDouble()
|
|
94
|
+
val pressure = event.getPressure(0).toDouble()
|
|
95
|
+
val orientation = event.getOrientation(0).toDouble()
|
|
96
|
+
// To get azimuth angle, we need to use orientation property (https://developer.android.com/develop/ui/compose/touch-input/stylus-input/advanced-stylus-features#orientation).
|
|
97
|
+
val azimuthAngle = (orientation + PI / 2).mod(2 * PI)
|
|
98
|
+
val tilts = spherical2tilt(altitudeAngle, azimuthAngle)
|
|
99
|
+
|
|
100
|
+
return StylusData(tilts.first, tilts.second, altitudeAngle, azimuthAngle, pressure)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -286,22 +286,11 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
|
|
|
286
286
|
return false
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
private fun updateBackgroundColor(backgroundColor: Int, selectable: Drawable?) {
|
|
289
|
+
private fun updateBackgroundColor(backgroundColor: Int, borderDrawable: Drawable, selectable: Drawable?) {
|
|
290
290
|
val colorDrawable = PaintDrawable(backgroundColor)
|
|
291
|
-
val borderDrawable = PaintDrawable(Color.TRANSPARENT)
|
|
292
291
|
|
|
293
292
|
if (hasBorderRadii) {
|
|
294
293
|
colorDrawable.setCornerRadii(buildBorderRadii())
|
|
295
|
-
borderDrawable.setCornerRadii(buildBorderRadii())
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (borderWidth > 0f) {
|
|
299
|
-
borderDrawable.paint.apply {
|
|
300
|
-
style = Paint.Style.STROKE
|
|
301
|
-
strokeWidth = borderWidth
|
|
302
|
-
color = borderColor ?: Color.BLACK
|
|
303
|
-
pathEffect = buildBorderStyle()
|
|
304
|
-
}
|
|
305
294
|
}
|
|
306
295
|
|
|
307
296
|
val layerDrawable = LayerDrawable(if (selectable != null) arrayOf(colorDrawable, selectable, borderDrawable) else arrayOf(colorDrawable, borderDrawable))
|
|
@@ -324,6 +313,7 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
|
|
|
324
313
|
}
|
|
325
314
|
|
|
326
315
|
val selectable = createSelectableDrawable()
|
|
316
|
+
val borderDrawable = createBorderDrawable()
|
|
327
317
|
|
|
328
318
|
if (hasBorderRadii && selectable is RippleDrawable) {
|
|
329
319
|
val mask = PaintDrawable(Color.WHITE)
|
|
@@ -334,13 +324,32 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R
|
|
|
334
324
|
if (useDrawableOnForeground && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
335
325
|
foreground = selectable
|
|
336
326
|
if (_backgroundColor != Color.TRANSPARENT) {
|
|
337
|
-
updateBackgroundColor(_backgroundColor, null)
|
|
327
|
+
updateBackgroundColor(_backgroundColor, borderDrawable, null)
|
|
338
328
|
}
|
|
339
329
|
} else if (_backgroundColor == Color.TRANSPARENT && rippleColor == null) {
|
|
340
|
-
background = selectable
|
|
330
|
+
background = LayerDrawable(arrayOf(selectable, borderDrawable))
|
|
341
331
|
} else {
|
|
342
|
-
updateBackgroundColor(_backgroundColor, selectable)
|
|
332
|
+
updateBackgroundColor(_backgroundColor, borderDrawable, selectable)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
private fun createBorderDrawable(): Drawable {
|
|
337
|
+
val borderDrawable = PaintDrawable(Color.TRANSPARENT)
|
|
338
|
+
|
|
339
|
+
if (hasBorderRadii) {
|
|
340
|
+
borderDrawable.setCornerRadii(buildBorderRadii())
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (borderWidth > 0f) {
|
|
344
|
+
borderDrawable.paint.apply {
|
|
345
|
+
style = Paint.Style.STROKE
|
|
346
|
+
strokeWidth = borderWidth
|
|
347
|
+
color = borderColor ?: Color.BLACK
|
|
348
|
+
pathEffect = buildBorderStyle()
|
|
349
|
+
}
|
|
343
350
|
}
|
|
351
|
+
|
|
352
|
+
return borderDrawable
|
|
344
353
|
}
|
|
345
354
|
|
|
346
355
|
private fun createSelectableDrawable(): Drawable? {
|
|
@@ -3,18 +3,21 @@ package com.swmansion.gesturehandler.react.eventbuilders
|
|
|
3
3
|
import com.facebook.react.bridge.WritableMap
|
|
4
4
|
import com.facebook.react.uimanager.PixelUtil
|
|
5
5
|
import com.swmansion.gesturehandler.core.HoverGestureHandler
|
|
6
|
+
import com.swmansion.gesturehandler.core.StylusData
|
|
6
7
|
|
|
7
8
|
class HoverGestureHandlerEventDataBuilder(handler: HoverGestureHandler) : GestureHandlerEventDataBuilder<HoverGestureHandler>(handler) {
|
|
8
9
|
private val x: Float
|
|
9
10
|
private val y: Float
|
|
10
11
|
private val absoluteX: Float
|
|
11
12
|
private val absoluteY: Float
|
|
13
|
+
private val stylusData: StylusData
|
|
12
14
|
|
|
13
15
|
init {
|
|
14
16
|
x = handler.lastRelativePositionX
|
|
15
17
|
y = handler.lastRelativePositionY
|
|
16
18
|
absoluteX = handler.lastPositionInWindowX
|
|
17
19
|
absoluteY = handler.lastPositionInWindowY
|
|
20
|
+
stylusData = handler.stylusData
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
override fun buildEventData(eventData: WritableMap) {
|
|
@@ -25,6 +28,10 @@ class HoverGestureHandlerEventDataBuilder(handler: HoverGestureHandler) : Gestur
|
|
|
25
28
|
putDouble("y", PixelUtil.toDIPFromPixel(y).toDouble())
|
|
26
29
|
putDouble("absoluteX", PixelUtil.toDIPFromPixel(absoluteX).toDouble())
|
|
27
30
|
putDouble("absoluteY", PixelUtil.toDIPFromPixel(absoluteY).toDouble())
|
|
31
|
+
|
|
32
|
+
if (stylusData.pressure != -1.0) {
|
|
33
|
+
putMap("stylusData", stylusData.toReadableMap())
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
}
|
|
30
37
|
}
|
|
@@ -3,6 +3,7 @@ package com.swmansion.gesturehandler.react.eventbuilders
|
|
|
3
3
|
import com.facebook.react.bridge.WritableMap
|
|
4
4
|
import com.facebook.react.uimanager.PixelUtil
|
|
5
5
|
import com.swmansion.gesturehandler.core.PanGestureHandler
|
|
6
|
+
import com.swmansion.gesturehandler.core.StylusData
|
|
6
7
|
|
|
7
8
|
class PanGestureHandlerEventDataBuilder(handler: PanGestureHandler) : GestureHandlerEventDataBuilder<PanGestureHandler>(handler) {
|
|
8
9
|
private val x: Float
|
|
@@ -13,6 +14,7 @@ class PanGestureHandlerEventDataBuilder(handler: PanGestureHandler) : GestureHan
|
|
|
13
14
|
private val translationY: Float
|
|
14
15
|
private val velocityX: Float
|
|
15
16
|
private val velocityY: Float
|
|
17
|
+
private val stylusData: StylusData
|
|
16
18
|
|
|
17
19
|
init {
|
|
18
20
|
x = handler.lastRelativePositionX
|
|
@@ -23,6 +25,7 @@ class PanGestureHandlerEventDataBuilder(handler: PanGestureHandler) : GestureHan
|
|
|
23
25
|
translationY = handler.translationY
|
|
24
26
|
velocityX = handler.velocityX
|
|
25
27
|
velocityY = handler.velocityY
|
|
28
|
+
stylusData = handler.stylusData
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
override fun buildEventData(eventData: WritableMap) {
|
|
@@ -37,6 +40,10 @@ class PanGestureHandlerEventDataBuilder(handler: PanGestureHandler) : GestureHan
|
|
|
37
40
|
putDouble("translationY", PixelUtil.toDIPFromPixel(translationY).toDouble())
|
|
38
41
|
putDouble("velocityX", PixelUtil.toDIPFromPixel(velocityX).toDouble())
|
|
39
42
|
putDouble("velocityY", PixelUtil.toDIPFromPixel(velocityY).toDouble())
|
|
43
|
+
|
|
44
|
+
if (stylusData.pressure != -1.0) {
|
|
45
|
+
putMap("stylusData", stylusData.toReadableMap())
|
|
46
|
+
}
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
}
|
|
@@ -26,12 +26,21 @@ target_include_directories(
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
find_package(ReactAndroid REQUIRED CONFIG)
|
|
29
|
-
|
|
30
|
-
target_link_libraries(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
if (ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
|
|
30
|
+
target_link_libraries(
|
|
31
|
+
${PACKAGE_NAME}
|
|
32
|
+
ReactAndroid::reactnative
|
|
33
|
+
ReactAndroid::jsi
|
|
34
|
+
)
|
|
35
|
+
elseif (ReactAndroid_VERSION_MINOR GREATER_EQUAL 75)
|
|
36
|
+
target_link_libraries(
|
|
37
|
+
${PACKAGE_NAME}
|
|
38
|
+
ReactAndroid::react_render_core
|
|
39
|
+
ReactAndroid::react_render_uimanager
|
|
40
|
+
ReactAndroid::react_render_graphics
|
|
41
|
+
ReactAndroid::jsi
|
|
42
|
+
ReactAndroid::react_nativemodule_core
|
|
43
|
+
)
|
|
44
|
+
else ()
|
|
45
|
+
message(FATAL_ERROR "react-native-gesture-handler on the New Architecture requires react-native 0.75 or newer.")
|
|
46
|
+
endif ()
|
|
@@ -233,10 +233,12 @@
|
|
|
233
233
|
recognizer.allowableMovement = [RCTConvert CGFloat:prop];
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
#if !TARGET_OS_TV
|
|
236
237
|
prop = config[@"numberOfPointers"];
|
|
237
238
|
if (prop != nil) {
|
|
238
239
|
recognizer.numberOfTouchesRequired = [RCTConvert CGFloat:prop];
|
|
239
240
|
}
|
|
241
|
+
#endif
|
|
240
242
|
}
|
|
241
243
|
|
|
242
244
|
#if !TARGET_OS_OSX
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import "RNPanHandler.h"
|
|
10
|
+
#import "RNGHStylusData.h"
|
|
10
11
|
|
|
11
12
|
#if TARGET_OS_OSX
|
|
12
13
|
|
|
@@ -31,6 +32,10 @@
|
|
|
31
32
|
@property (nonatomic) CGFloat failOffsetYEnd;
|
|
32
33
|
@property (nonatomic) CGFloat activateAfterLongPress;
|
|
33
34
|
|
|
35
|
+
#if !TARGET_OS_OSX && !TARGET_OS_TV
|
|
36
|
+
@property (atomic, readonly, strong) RNGHStylusData *stylusData;
|
|
37
|
+
#endif
|
|
38
|
+
|
|
34
39
|
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler;
|
|
35
40
|
|
|
36
41
|
@end
|
|
@@ -80,6 +85,28 @@
|
|
|
80
85
|
}
|
|
81
86
|
#endif
|
|
82
87
|
|
|
88
|
+
#if !TARGET_OS_OSX && !TARGET_OS_TV
|
|
89
|
+
- (void)tryUpdateStylusData:(UIEvent *)event
|
|
90
|
+
{
|
|
91
|
+
UITouch *touch = [[event allTouches] anyObject];
|
|
92
|
+
|
|
93
|
+
if (touch.type != UITouchTypePencil) {
|
|
94
|
+
return;
|
|
95
|
+
} else if (_stylusData == nil) {
|
|
96
|
+
_stylusData = [[RNGHStylusData alloc] init];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_stylusData.altitudeAngle = touch.altitudeAngle;
|
|
100
|
+
_stylusData.azimuthAngle = [touch azimuthAngleInView:nil];
|
|
101
|
+
_stylusData.pressure = touch.force / touch.maximumPossibleForce;
|
|
102
|
+
|
|
103
|
+
CGPoint tilts = ghSpherical2tilt(_stylusData.altitudeAngle, _stylusData.azimuthAngle);
|
|
104
|
+
|
|
105
|
+
_stylusData.tiltX = tilts.x;
|
|
106
|
+
_stylusData.tiltY = tilts.y;
|
|
107
|
+
}
|
|
108
|
+
#endif
|
|
109
|
+
|
|
83
110
|
- (void)activateAfterLongPress
|
|
84
111
|
{
|
|
85
112
|
self.state = UIGestureRecognizerStateBegan;
|
|
@@ -102,6 +129,8 @@
|
|
|
102
129
|
} else {
|
|
103
130
|
super.minimumNumberOfTouches = _realMinimumNumberOfTouches;
|
|
104
131
|
}
|
|
132
|
+
|
|
133
|
+
[self tryUpdateStylusData:event];
|
|
105
134
|
#endif
|
|
106
135
|
|
|
107
136
|
#if TARGET_OS_OSX
|
|
@@ -150,17 +179,28 @@
|
|
|
150
179
|
[self setTranslation:CGPointMake(0, 0) inView:self.view];
|
|
151
180
|
}
|
|
152
181
|
}
|
|
182
|
+
|
|
183
|
+
[self tryUpdateStylusData:event];
|
|
153
184
|
#endif
|
|
154
185
|
}
|
|
155
186
|
|
|
156
187
|
- (void)interactionsEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
|
157
188
|
{
|
|
158
189
|
[_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
|
|
190
|
+
|
|
191
|
+
#if !TARGET_OS_TV && !TARGET_OS_OSX
|
|
192
|
+
[self tryUpdateStylusData:event];
|
|
193
|
+
#endif
|
|
159
194
|
}
|
|
160
195
|
|
|
161
196
|
- (void)interactionsCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
|
162
197
|
{
|
|
163
198
|
[_gestureHandler.pointerTracker touchesCancelled:touches withEvent:event];
|
|
199
|
+
|
|
200
|
+
#if !TARGET_OS_TV && !TARGET_OS_OSX
|
|
201
|
+
[self tryUpdateStylusData:event];
|
|
202
|
+
#endif
|
|
203
|
+
|
|
164
204
|
[self reset];
|
|
165
205
|
}
|
|
166
206
|
|
|
@@ -224,6 +264,10 @@
|
|
|
224
264
|
self.enabled = YES;
|
|
225
265
|
[super reset];
|
|
226
266
|
[_gestureHandler reset];
|
|
267
|
+
|
|
268
|
+
#if !TARGET_OS_TV && !TARGET_OS_OSX
|
|
269
|
+
_stylusData = nil;
|
|
270
|
+
#endif
|
|
227
271
|
}
|
|
228
272
|
|
|
229
273
|
- (void)updateHasCustomActivationCriteria
|
|
@@ -405,17 +449,23 @@
|
|
|
405
449
|
withTranslation:[recognizer translationInView:recognizer.view.window.contentView]
|
|
406
450
|
withVelocity:[recognizer velocityInView:recognizer.view.window.contentView]
|
|
407
451
|
withNumberOfTouches:1
|
|
408
|
-
withPointerType:RNGestureHandlerMouse
|
|
452
|
+
withPointerType:RNGestureHandlerMouse
|
|
453
|
+
withStylusData:nil];
|
|
409
454
|
}
|
|
410
455
|
#else
|
|
411
456
|
- (RNGestureHandlerEventExtraData *)eventExtraData:(UIPanGestureRecognizer *)recognizer
|
|
412
457
|
{
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
458
|
+
RNBetterPanGestureRecognizer *panRecognizer = (RNBetterPanGestureRecognizer *)recognizer;
|
|
459
|
+
|
|
460
|
+
return [RNGestureHandlerEventExtraData
|
|
461
|
+
forPan:[recognizer locationInView:recognizer.view]
|
|
462
|
+
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
|
|
463
|
+
withTranslation:[recognizer translationInView:recognizer.view.window]
|
|
464
|
+
withVelocity:[recognizer velocityInView:recognizer.view.window]
|
|
465
|
+
withNumberOfTouches:recognizer.numberOfTouches
|
|
466
|
+
withPointerType:_pointerType
|
|
467
|
+
withStylusData:[panRecognizer.stylusData toDictionary]]; // In Objective-C calling method on nil returns
|
|
468
|
+
// nil, therefore this line does not crash.
|
|
419
469
|
}
|
|
420
470
|
#endif
|
|
421
471
|
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
#if TARGET_OS_OSX
|
|
150
150
|
- (RNGestureHandlerEventExtraData *)eventExtraData:(NSRotationGestureRecognizer *)recognizer
|
|
151
151
|
{
|
|
152
|
-
return [RNGestureHandlerEventExtraData forRotation
|
|
152
|
+
return [RNGestureHandlerEventExtraData forRotation:-recognizer.rotation
|
|
153
153
|
withAnchorPoint:[recognizer locationInView:recognizer.view]
|
|
154
154
|
withVelocity:((RNBetterRotationRecognizer *)recognizer).velocity
|
|
155
155
|
withNumberOfTouches:2
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNGHStylusData.h
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Michał Bert on 18/09/2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#ifndef RNGHStylusData_h
|
|
9
|
+
#define RNGHStylusData_h
|
|
10
|
+
|
|
11
|
+
@interface RNGHStylusData : NSObject
|
|
12
|
+
|
|
13
|
+
@property (atomic, assign) double tiltX;
|
|
14
|
+
@property (atomic, assign) double tiltY;
|
|
15
|
+
@property (atomic, assign) double altitudeAngle;
|
|
16
|
+
@property (atomic, assign) double azimuthAngle;
|
|
17
|
+
@property (atomic, assign) double pressure;
|
|
18
|
+
|
|
19
|
+
- (NSDictionary *)toDictionary;
|
|
20
|
+
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
static CGPoint ghSpherical2tilt(double altitudeAngle, double azimuthAngle)
|
|
24
|
+
{
|
|
25
|
+
CGPoint tilts = {.x = 0.0, .y = 0.0};
|
|
26
|
+
|
|
27
|
+
const double radToDeg = 180 / M_PI;
|
|
28
|
+
const double eps = 0.000000001;
|
|
29
|
+
|
|
30
|
+
if (altitudeAngle < eps) {
|
|
31
|
+
// the pen is in the X-Y plane
|
|
32
|
+
if (azimuthAngle < eps || fabs(azimuthAngle - 2 * M_PI) < eps) {
|
|
33
|
+
// pen is on positive X axis
|
|
34
|
+
tilts.x = M_PI_2;
|
|
35
|
+
}
|
|
36
|
+
if (fabs(azimuthAngle - M_PI_2) < eps) {
|
|
37
|
+
// pen is on positive Y axis
|
|
38
|
+
tilts.y = M_PI_2;
|
|
39
|
+
}
|
|
40
|
+
if (fabs(azimuthAngle - M_PI) < eps) {
|
|
41
|
+
// pen is on negative X axis
|
|
42
|
+
tilts.x = -M_PI_2;
|
|
43
|
+
}
|
|
44
|
+
if (fabs(azimuthAngle - 3 * M_PI_2) < eps) {
|
|
45
|
+
// pen is on negative Y axis
|
|
46
|
+
tilts.y = -M_PI_2;
|
|
47
|
+
}
|
|
48
|
+
if (azimuthAngle > eps && fabs(azimuthAngle - M_PI_2) < eps) {
|
|
49
|
+
tilts.x = M_PI_2;
|
|
50
|
+
tilts.y = M_PI_2;
|
|
51
|
+
}
|
|
52
|
+
if (fabs(azimuthAngle - M_PI_2) > eps && fabs(azimuthAngle - M_PI) < eps) {
|
|
53
|
+
tilts.x = -M_PI_2;
|
|
54
|
+
tilts.y = M_PI_2;
|
|
55
|
+
}
|
|
56
|
+
if (azimuthAngle - M_PI > eps && fabs(azimuthAngle - 3 * M_PI_2) < eps) {
|
|
57
|
+
tilts.x = -M_PI_2;
|
|
58
|
+
tilts.y = -M_PI_2;
|
|
59
|
+
}
|
|
60
|
+
if (fabs(azimuthAngle - 3 * M_PI_2) > eps && fabs(azimuthAngle - 2 * M_PI) < eps) {
|
|
61
|
+
tilts.x = M_PI_2;
|
|
62
|
+
tilts.y = -M_PI_2;
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const double tanAlt = tan(altitudeAngle);
|
|
66
|
+
|
|
67
|
+
tilts.x = atan(cos(azimuthAngle) / tanAlt);
|
|
68
|
+
tilts.y = atan(sin(azimuthAngle) / tanAlt);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
tilts.x = round(tilts.x * radToDeg);
|
|
72
|
+
tilts.y = round(tilts.y * radToDeg);
|
|
73
|
+
|
|
74
|
+
return tilts;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#endif /* RNGHStylusData_h */
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNGHStylusData.m
|
|
3
|
+
// DoubleConversion
|
|
4
|
+
//
|
|
5
|
+
// Created by Michał Bert on 18/09/2024.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "RNGHStylusData.h"
|
|
9
|
+
#import <Foundation/Foundation.h>
|
|
10
|
+
|
|
11
|
+
@implementation RNGHStylusData
|
|
12
|
+
|
|
13
|
+
- (instancetype)init
|
|
14
|
+
{
|
|
15
|
+
if (self = [super init]) {
|
|
16
|
+
self.tiltX = 0;
|
|
17
|
+
self.tiltY = 0;
|
|
18
|
+
self.altitudeAngle = M_PI_2;
|
|
19
|
+
self.azimuthAngle = 0;
|
|
20
|
+
self.pressure = 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return self;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (NSDictionary *)toDictionary
|
|
27
|
+
{
|
|
28
|
+
return @{
|
|
29
|
+
@"tiltX" : @(_tiltX),
|
|
30
|
+
@"tiltY" : @(_tiltY),
|
|
31
|
+
@"altitudeAngle" : @(_altitudeAngle),
|
|
32
|
+
@"azimuthAngle" : @(_azimuthAngle),
|
|
33
|
+
@"pressure" : @(_pressure),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@end
|