Skip to content

Commit ea0f839

Browse files
committed
Implement basic state machine for button
1 parent 0f4ffd7 commit ea0f839

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ class RNGestureHandlerButtonViewManager :
436436
private var underlayDrawable: PaintDrawable? = null
437437
private var pressInTimestamp = 0L
438438
private var pendingPressOut: Runnable? = null
439+
private var pendingLongPress: Runnable? = null
439440
private var pendingHoverOut: Choreographer.FrameCallback? = null
440441
private var isPointerInsideBounds = false
441442
private var isHovered = false
@@ -520,6 +521,93 @@ class RNGestureHandlerButtonViewManager :
520521
}
521522
}
522523

524+
private var longPressDetected = false
525+
526+
// Cannot rely on isPointerInsideBounds because it's set to false during motion event processing
527+
// which happens before the final state change is handled (state change is triggered by the motion
528+
// event).
529+
private var lastEventWasInside = false
530+
531+
override fun onHandlerUpdate(handler: NativeViewGestureHandler) {
532+
if (handler.isWithinBounds == lastEventWasInside) {
533+
return
534+
}
535+
536+
if (handler.isWithinBounds) {
537+
dispatchJSEvent(EventType.PressIn)
538+
} else {
539+
dispatchJSEvent(EventType.PressOut)
540+
541+
pendingLongPress?.let {
542+
this.handler?.removeCallbacks(it)
543+
pendingLongPress = null
544+
}
545+
}
546+
}
547+
548+
override fun onHandlerStateChange(handler: NativeViewGestureHandler, newState: Int, prevState: Int) {
549+
// Capture local copy, since lastEventWasInside can change during this method
550+
// Specifically PressOut -> Press scenario on STATE_END
551+
val localLastEventWasInside = lastEventWasInside
552+
553+
if (newState == GestureHandler.STATE_BEGAN) {
554+
dispatchJSEvent(EventType.PressIn)
555+
556+
val runnable = Runnable {
557+
pendingLongPress = null
558+
longPressDetected = true
559+
dispatchJSEvent(EventType.LongPress)
560+
}
561+
longPressDetected = false
562+
pendingLongPress = runnable
563+
this.handler?.postDelayed(runnable, longPressDuration.toLong())
564+
}
565+
566+
if (newState == GestureHandler.STATE_END ||
567+
newState == GestureHandler.STATE_FAILED ||
568+
newState == GestureHandler.STATE_CANCELLED
569+
) {
570+
if (localLastEventWasInside) {
571+
dispatchJSEvent(EventType.PressOut)
572+
}
573+
574+
pendingLongPress?.let {
575+
this.handler?.removeCallbacks(it)
576+
pendingLongPress = null
577+
}
578+
}
579+
580+
if (newState == GestureHandler.STATE_END && !longPressDetected && localLastEventWasInside) {
581+
dispatchJSEvent(EventType.Press)
582+
}
583+
584+
if (newState == GestureHandler.STATE_END ||
585+
newState == GestureHandler.STATE_FAILED ||
586+
newState == GestureHandler.STATE_CANCELLED
587+
) {
588+
dispatchJSEvent(EventType.InteractionFinished)
589+
}
590+
}
591+
592+
private fun dispatchJSEvent(type: EventType) {
593+
when (type) {
594+
EventType.Press -> {
595+
Log.w("RNGH", "onPress")
596+
}
597+
EventType.PressIn -> {
598+
lastEventWasInside = true
599+
Log.w("RNGH", "onPressIn")
600+
}
601+
EventType.PressOut -> {
602+
lastEventWasInside = false
603+
Log.w("RNGH", "onPressOut")
604+
}
605+
EventType.LongPress -> {
606+
Log.w("RNGH", "longPress")
607+
}
608+
}
609+
}
610+
523611
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
524612
if (super.onInterceptTouchEvent(event)) {
525613
return true
@@ -912,6 +1000,8 @@ class RNGestureHandlerButtonViewManager :
9121000
override fun onDetachedFromWindow() {
9131001
pendingPressOut?.let { handler?.removeCallbacks(it) }
9141002
pendingPressOut = null
1003+
pendingLongPress?.let { handler?.removeCallbacks(it) }
1004+
pendingLongPress = null
9151005
cancelPendingHoverOut()
9161006
currentAnimator?.cancel()
9171007
currentAnimator = null
@@ -1104,6 +1194,13 @@ class RNGestureHandlerButtonViewManager :
11041194
}
11051195
}
11061196
}
1197+
1198+
enum class EventType {
1199+
Press,
1200+
PressIn,
1201+
PressOut,
1202+
LongPress
1203+
}
11071204
}
11081205

11091206
companion object {

0 commit comments

Comments
 (0)