Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class NativeViewGestureHandler : GestureHandler() {
is ReactTextView -> this.hook = TextViewHook()
is ReactViewGroup -> this.hook = ReactViewGroupHook()
}
hook.attachHandler(this)
}

override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
Expand Down Expand Up @@ -166,6 +167,7 @@ class NativeViewGestureHandler : GestureHandler() {
override fun onFail() = dispatchCancelEventToView()

override fun onReset() {
hook.detachHandler()
this.hook = defaultHook
lastActiveUpdate = null
}
Expand Down Expand Up @@ -275,6 +277,19 @@ class NativeViewGestureHandler : GestureHandler() {
* Passes the event down to the underlying view using the correct method.
*/
fun sendTouchEvent(view: View?, event: MotionEvent) = view?.onTouchEvent(event)

/**
* Called after the handler has prepared itself on this hook's view. The hook
* can retain the handler reference to drive state transitions from the view's
* own lifecycle (e.g. calling `activate()`, `fail()` or `cancel()` in
* response to native view state changes).
*/
fun attachHandler(handler: NativeViewGestureHandler) = Unit
Comment thread
j-piasecki marked this conversation as resolved.

/**
* Called on handler reset so the hook can drop its retained handler reference.
*/
fun detachHandler() = Unit
}

private class TextViewHook : NativeViewGestureHandlerHook {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import com.facebook.react.uimanager.style.BorderStyle
import com.facebook.react.uimanager.style.LogicalEdge
import com.facebook.react.viewmanagers.RNGestureHandlerButtonManagerDelegate
import com.facebook.react.viewmanagers.RNGestureHandlerButtonManagerInterface
import com.swmansion.gesturehandler.core.GestureHandler
import com.swmansion.gesturehandler.core.NativeViewGestureHandler
import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager.ButtonViewGroup

Expand Down Expand Up @@ -380,6 +381,7 @@ class RNGestureHandlerButtonViewManager :
private var pressInTimestamp = 0L
private var pendingPressOut: Runnable? = null
private var isPointerInsideBounds = false
private var attachedHandler: NativeViewGestureHandler? = null

// When non-null the ripple is drawn in dispatchDraw (above background, below children).
// When null the ripple lives on the foreground drawable instead.
Expand Down Expand Up @@ -715,6 +717,14 @@ class RNGestureHandlerButtonViewManager :
}
}

override fun attachHandler(handler: NativeViewGestureHandler) {
attachedHandler = handler
}

override fun detachHandler() {
attachedHandler = null
}

override fun canBegin(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_CANCEL ||
event.action == MotionEvent.ACTION_UP ||
Expand Down Expand Up @@ -816,6 +826,9 @@ class RNGestureHandlerButtonViewManager :
super.setPressed(pressed)

if (pressed) {
attachedHandler?.takeIf {
it.state == GestureHandler.STATE_UNDETERMINED || it.state == GestureHandler.STATE_BEGAN
}?.activate()
animatePressIn()
} else {
animatePressOut()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const Touchable = (props: TouchableProps) => {
}
}, [onLongPress, delayLongPress, wrappedLongPress]);

const onBegin = useCallback(
const onActivate = useCallback(
(e: CallbackEventType) => {
if (!e.pointerInside) {
pointerState.current = PointerState.OUTSIDE;
Expand All @@ -79,26 +79,10 @@ export const Touchable = (props: TouchableProps) => {

pointerState.current = PointerState.INSIDE;
},
[startLongPressTimer, onPressIn]
[onPressIn, startLongPressTimer]
);

const onActivate = useCallback((e: CallbackEventType) => {
if (!e.pointerInside && longPressTimeout.current !== undefined) {
clearTimeout(longPressTimeout.current);
longPressTimeout.current = undefined;
}
}, []);

const onDeactivate = useCallback(
(e: EndCallbackEventType) => {
if (!e.canceled && !longPressDetected.current && e.pointerInside) {
onPress?.(e);
}
},
[onPress]
);

const onFinalize = useCallback(
(e: EndCallbackEventType) => {
if (pointerState.current === PointerState.INSIDE) {
onPressOut?.(e);
Expand All @@ -110,8 +94,12 @@ export const Touchable = (props: TouchableProps) => {
clearTimeout(longPressTimeout.current);
longPressTimeout.current = undefined;
}

if (!e.canceled && !longPressDetected.current && e.pointerInside) {
onPress?.(e);
}
},
[onPressOut]
[onPress, onPressOut]
);

const onUpdate = useCallback(
Expand Down Expand Up @@ -155,10 +143,8 @@ export const Touchable = (props: TouchableProps) => {
{...rippleProps}
ref={ref ?? null}
enabled={!disabled}
onBegin={onBegin}
onActivate={onActivate}
onDeactivate={onDeactivate}
onFinalize={onFinalize}
onUpdate={onUpdate}
defaultOpacity={defaultOpacity}
defaultUnderlayOpacity={defaultUnderlayOpacity}
Expand Down
Loading