@@ -11,12 +11,15 @@ import android.view.MotionEvent.PointerProperties
11
11
import android.view.View
12
12
import com.facebook.react.bridge.Arguments
13
13
import com.facebook.react.bridge.ReactContext
14
+ import com.facebook.react.bridge.ReadableMap
15
+ import com.facebook.react.bridge.ReadableType
14
16
import com.facebook.react.bridge.UiThreadUtil
15
17
import com.facebook.react.bridge.WritableArray
16
18
import com.facebook.react.uimanager.PixelUtil
17
19
import com.swmansion.gesturehandler.BuildConfig
18
20
import com.swmansion.gesturehandler.RNSVGHitTester
19
21
import com.swmansion.gesturehandler.react.RNGestureHandlerTouchEvent
22
+ import com.swmansion.gesturehandler.react.eventbuilders.GestureHandlerEventDataBuilder
20
23
import java.lang.IllegalStateException
21
24
import java.util.*
22
25
@@ -36,7 +39,17 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
36
39
var isWithinBounds = false
37
40
private set
38
41
var isEnabled = true
39
- private set
42
+ private set(enabled) {
43
+ // Don't cancel handler when not changing the value of the isEnabled, executing it always caused
44
+ // handlers to be cancelled on re-render because that's the moment when the config is updated.
45
+ // If the enabled prop "changed" from true to true the handler would get cancelled.
46
+ if (view != null && isEnabled != enabled) {
47
+ // If view is set then handler is in "active" state. In that case we want to "cancel" handler
48
+ // when it changes enabled state so that it gets cleared from the orchestrator
49
+ UiThreadUtil .runOnUiThread { cancel() }
50
+ }
51
+ field = enabled
52
+ }
40
53
var actionType = 0
41
54
42
55
var changedTouchesPayload: WritableArray ? = null
@@ -62,9 +75,9 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
62
75
63
76
private var lastEventOffsetX = 0f
64
77
private var lastEventOffsetY = 0f
65
- private var shouldCancelWhenOutside = false
66
78
var numberOfPointers = 0
67
- private set
79
+ protected set
80
+ protected var shouldCancelWhenOutside = false
68
81
protected var orchestrator: GestureHandlerOrchestrator ? = null
69
82
private var onTouchEventListener: OnTouchEventListener ? = null
70
83
private var interactionController: GestureHandlerInteractionController ? = null
@@ -100,11 +113,12 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
100
113
}
101
114
102
115
open fun resetConfig () {
103
- needsPointerData = false
104
- manualActivation = false
105
- shouldCancelWhenOutside = false
106
- isEnabled = true
107
- hitSlop = null
116
+ needsPointerData = DEFAULT_NEEDS_POINTER_DATA
117
+ manualActivation = DEFAULT_MANUAL_ACTIVATION
118
+ shouldCancelWhenOutside = DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE
119
+ isEnabled = DEFAULT_IS_ENABLED
120
+ hitSlop = DEFAULT_HIT_SLOP
121
+ mouseButton = DEFAULT_MOUSE_BUTTON
108
122
}
109
123
110
124
fun hasCommonPointers (other : GestureHandler <* >): Boolean {
@@ -116,24 +130,6 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
116
130
return false
117
131
}
118
132
119
- fun setShouldCancelWhenOutside (shouldCancelWhenOutside : Boolean ): ConcreteGestureHandlerT =
120
- applySelf { this .shouldCancelWhenOutside = shouldCancelWhenOutside }
121
-
122
- fun setEnabled (enabled : Boolean ): ConcreteGestureHandlerT = applySelf {
123
- // Don't cancel handler when not changing the value of the isEnabled, executing it always caused
124
- // handlers to be cancelled on re-render because that's the moment when the config is updated.
125
- // If the enabled prop "changed" from true to true the handler would get cancelled.
126
- if (view != null && isEnabled != enabled) {
127
- // If view is set then handler is in "active" state. In that case we want to "cancel" handler
128
- // when it changes enabled state so that it gets cleared from the orchestrator
129
- UiThreadUtil .runOnUiThread { cancel() }
130
- }
131
- isEnabled = enabled
132
- }
133
-
134
- fun setManualActivation (manualActivation : Boolean ): ConcreteGestureHandlerT =
135
- applySelf { this .manualActivation = manualActivation }
136
-
137
133
fun setHitSlop (
138
134
leftPad : Float ,
139
135
topPad : Float ,
@@ -164,10 +160,6 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
164
160
fun setInteractionController (controller : GestureHandlerInteractionController ? ): ConcreteGestureHandlerT =
165
161
applySelf { interactionController = controller }
166
162
167
- fun setMouseButton (mouseButton : Int ) = apply {
168
- this .mouseButton = mouseButton
169
- }
170
-
171
163
fun prepare (view : View ? , orchestrator : GestureHandlerOrchestrator ? ) {
172
164
check(! (this .view != null || this .orchestrator != null )) { " Already prepared or hasn't been reset" }
173
165
Arrays .fill(trackedPointerIDs, - 1 )
@@ -822,7 +814,104 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
822
814
val lastPositionInWindowY: Float
823
815
get() = lastAbsolutePositionY + lastEventOffsetY - windowOffset[1 ]
824
816
817
+ abstract class Factory <T : GestureHandler <T >> {
818
+ abstract val type: Class <T >
819
+ abstract val name: String
820
+ abstract fun create (context : Context ? ): T
821
+ open fun setConfig (handler : T , config : ReadableMap ) {
822
+ handler.resetConfig()
823
+ if (config.hasKey(KEY_SHOULD_CANCEL_WHEN_OUTSIDE )) {
824
+ handler.shouldCancelWhenOutside = config.getBoolean(KEY_SHOULD_CANCEL_WHEN_OUTSIDE )
825
+ }
826
+ if (config.hasKey(KEY_ENABLED )) {
827
+ handler.isEnabled = config.getBoolean(KEY_ENABLED )
828
+ }
829
+ if (config.hasKey(KEY_HIT_SLOP )) {
830
+ handleHitSlopProperty(handler, config)
831
+ }
832
+ if (config.hasKey(KEY_NEEDS_POINTER_DATA )) {
833
+ handler.needsPointerData = config.getBoolean(KEY_NEEDS_POINTER_DATA )
834
+ }
835
+ if (config.hasKey(KEY_MANUAL_ACTIVATION )) {
836
+ handler.manualActivation = config.getBoolean(KEY_MANUAL_ACTIVATION )
837
+ }
838
+ if (config.hasKey(KEY_MOUSE_BUTTON )) {
839
+ handler.mouseButton = config.getInt(KEY_MOUSE_BUTTON )
840
+ }
841
+ }
842
+
843
+ abstract fun createEventBuilder (handler : T ): GestureHandlerEventDataBuilder <T >
844
+
845
+ companion object {
846
+ private const val KEY_SHOULD_CANCEL_WHEN_OUTSIDE = " shouldCancelWhenOutside"
847
+ private const val KEY_ENABLED = " enabled"
848
+ private const val KEY_NEEDS_POINTER_DATA = " needsPointerData"
849
+ private const val KEY_MANUAL_ACTIVATION = " manualActivation"
850
+ private const val KEY_MOUSE_BUTTON = " mouseButton"
851
+ private const val KEY_HIT_SLOP = " hitSlop"
852
+ private const val KEY_HIT_SLOP_LEFT = " left"
853
+ private const val KEY_HIT_SLOP_TOP = " top"
854
+ private const val KEY_HIT_SLOP_RIGHT = " right"
855
+ private const val KEY_HIT_SLOP_BOTTOM = " bottom"
856
+ private const val KEY_HIT_SLOP_VERTICAL = " vertical"
857
+ private const val KEY_HIT_SLOP_HORIZONTAL = " horizontal"
858
+ private const val KEY_HIT_SLOP_WIDTH = " width"
859
+ private const val KEY_HIT_SLOP_HEIGHT = " height"
860
+
861
+ private fun handleHitSlopProperty (handler : GestureHandler <* >, config : ReadableMap ) {
862
+ if (config.getType(KEY_HIT_SLOP ) == ReadableType .Number ) {
863
+ val hitSlop = PixelUtil .toPixelFromDIP(config.getDouble(KEY_HIT_SLOP ))
864
+ handler.setHitSlop(hitSlop, hitSlop, hitSlop, hitSlop, GestureHandler .HIT_SLOP_NONE , GestureHandler .HIT_SLOP_NONE )
865
+ } else {
866
+ val hitSlop = config.getMap(KEY_HIT_SLOP )!!
867
+ var left = GestureHandler .HIT_SLOP_NONE
868
+ var top = GestureHandler .HIT_SLOP_NONE
869
+ var right = GestureHandler .HIT_SLOP_NONE
870
+ var bottom = GestureHandler .HIT_SLOP_NONE
871
+ var width = GestureHandler .HIT_SLOP_NONE
872
+ var height = GestureHandler .HIT_SLOP_NONE
873
+ if (hitSlop.hasKey(KEY_HIT_SLOP_HORIZONTAL )) {
874
+ val horizontalPad = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_HORIZONTAL ))
875
+ right = horizontalPad
876
+ left = right
877
+ }
878
+ if (hitSlop.hasKey(KEY_HIT_SLOP_VERTICAL )) {
879
+ val verticalPad = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_VERTICAL ))
880
+ bottom = verticalPad
881
+ top = bottom
882
+ }
883
+ if (hitSlop.hasKey(KEY_HIT_SLOP_LEFT )) {
884
+ left = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_LEFT ))
885
+ }
886
+ if (hitSlop.hasKey(KEY_HIT_SLOP_TOP )) {
887
+ top = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_TOP ))
888
+ }
889
+ if (hitSlop.hasKey(KEY_HIT_SLOP_RIGHT )) {
890
+ right = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_RIGHT ))
891
+ }
892
+ if (hitSlop.hasKey(KEY_HIT_SLOP_BOTTOM )) {
893
+ bottom = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_BOTTOM ))
894
+ }
895
+ if (hitSlop.hasKey(KEY_HIT_SLOP_WIDTH )) {
896
+ width = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_WIDTH ))
897
+ }
898
+ if (hitSlop.hasKey(KEY_HIT_SLOP_HEIGHT )) {
899
+ height = PixelUtil .toPixelFromDIP(hitSlop.getDouble(KEY_HIT_SLOP_HEIGHT ))
900
+ }
901
+ handler.setHitSlop(left, top, right, bottom, width, height)
902
+ }
903
+ }
904
+ }
905
+ }
906
+
825
907
companion object {
908
+ private const val DEFAULT_NEEDS_POINTER_DATA = false
909
+ private const val DEFAULT_MANUAL_ACTIVATION = false
910
+ private const val DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE = false
911
+ private const val DEFAULT_IS_ENABLED = true
912
+ private val DEFAULT_HIT_SLOP = null
913
+ private const val DEFAULT_MOUSE_BUTTON = 0
914
+
826
915
const val STATE_UNDETERMINED = 0
827
916
const val STATE_FAILED = 1
828
917
const val STATE_BEGAN = 2
0 commit comments