Skip to content

Commit 67cdbb0

Browse files
authored
[Android] Restore button pressed state on drag in (#4118)
## Description Native button implementation wasn't restoring the `pressed` state when the pointer was moved back into the area of the button. This caused two issues: 1. Since the press-out animation was triggered by moving out of the button and setting pressed to `false`, this effectively made the buttons stuck in the pressed-in animation when moving out, moving back in, and releasing the pointer over the button. 2. Ripple animation was triggering the first time the button was pressed, cleared on move out, and not reapplied on subsequent moves in. This PR addresses both of these. ## Test plan <details> <summary>Expand</summary> ```jsx import React, { useState } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { Touchable } from 'react-native-gesture-handler'; import { COLORS } from '../common'; export default function LegacyRectButtonActivateOnStartExample() { const [log, setLog] = useState<string[]>([]); const [active, setActive] = useState(false); const pushLog = (message: string) => { setLog((prev) => [...prev, `[${new Date().toLocaleTimeString()}] ${message}`].slice(-8) ); }; return ( <View style={styles.container}> <Touchable style={{ width: 220, paddingVertical: 20, borderRadius: 12, backgroundColor: active ? COLORS.DARK_PURPLE : '#A0D5EF', alignItems: 'center', justifyContent: 'center', overflow: 'hidden', }} underlayColor={COLORS.RED} activeScale={1.2} cancelOnLeave={false} androidRipple={{}} onPress={() => pushLog('onPress')} onLongPress={() => pushLog('onLongPress')} onPressIn={() => { pushLog('onPressIn'); setActive(false);}} onPressOut={() => { pushLog('onPressOut'); setActive(false); }}> <Text>Hold me</Text> </Touchable> <View style={styles.logBox}> <Text style={styles.logTitle}>Event log</Text> {Array.from({ length: 8 }).map((_, index) => ( <Text key={index} style={styles.logEntry}> {log[index] ?? ' '} </Text> ))} </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24, gap: 16, }, title: { fontSize: 20, fontWeight: '700', color: COLORS.NAVY, }, hint: { textAlign: 'center', opacity: 0.7, fontSize: 14, }, button: { width: 220, paddingVertical: 20, borderRadius: 12, backgroundColor: '#A0D5EF', alignItems: 'center', justifyContent: 'center', overflow: 'hidden', }, buttonLabel: { fontSize: 16, fontWeight: '600', color: COLORS.NAVY, }, logBox: { width: '100%', padding: 12, borderRadius: 8, backgroundColor: COLORS.offWhite, gap: 4, }, logTitle: { fontSize: 13, fontWeight: '700', marginBottom: 4, color: COLORS.NAVY, }, logEntry: { fontSize: 12, fontFamily: 'Menlo', }, }); ``` </details> |Before|After| |-|-| |<video src="https://github.com/user-attachments/assets/45affbcb-dc6c-469b-9bb8-b3ef2bd3eff5" />|<video src="https://github.com/user-attachments/assets/dcee50a3-5e25-476a-8141-1b0750a0e59a" />|
1 parent 7b46018 commit 67cdbb0

1 file changed

Lines changed: 3 additions & 1 deletion

File tree

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,9 @@ class RNGestureHandlerButtonViewManager :
493493
if (inside != isPointerInsideBounds) {
494494
isPointerInsideBounds = inside
495495
if (inside) {
496-
animatePressIn()
496+
// Re-establish View's pressed flag to restore ripple and the
497+
// UP handler runs its normal release cleanup.
498+
setPressed(true)
497499
} else {
498500
animatePressOut()
499501
}

0 commit comments

Comments
 (0)