Skip to content

Conversation

ridwansameer
Copy link

Adding in this PR based on a requirement we had.

Sometimes wrapping the Rive component with a TouchableOpacity or other Touchable (Other than TouchableWithoutFeedback) would not work. Because the inner TouchableWithoutFeedback is taking priority.

Therefore adding a custom onPress prop which can be called when the animation is clicked, as well as an option to disable the default handling

Our Use Case:

  • Animation has an onClick trigger
  • We want to trigger another side effect when animation is clicked
  • We cannot use a Touchable because it does not work
  • So using the new onPress to call riveRef.current?.setInputState to trigger the animation as well as our side effect

@ridwansameer
Copy link
Author

The example Podfile.lock also seems to be using an older version of Rive, so this updated it.

@HayesGordon
Copy link
Contributor

Hi @ridwansameer thank you for the PR. We'll take a look at it, as it is helpful to be able to disable the touch inputs.

As a side note, you may find events more helpful for this use case if you want to trigger some side effect from an event that occurs in an animation (communication from animation to code). See here: https://help.rive.app/runtimes/rive-events

@ridwansameer
Copy link
Author

Yes we considered events, but we felt React native telling Rive what state to change to instead of RN doing its thing based on an event from Rive to be a bit more of a better event direction. Not sure if everyone would agree.

With regards to this PR, I noticed that the touch event still does go through on a different rive file even though I was using the updated code (With patch package). Wondering if there's some lower level onClick (maybe from the native side) that is triggering it

Copy link

@roti-c137 roti-c137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes in my work I do require a touch event that is wrapped outside of Rive.

Or is there any other way to get the touch event from Rive's own touchablewithoutfeedback that I missed out?

animationName,
stateMachineName,
testID,
disableDefaultTouchHandling = false,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can reduce this variable and do something like this
const isDisableDefaultTouch = onPress

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can ignore this if we need to support onPressIn at the same time too.

@CacaoRick
Copy link

CacaoRick commented Jun 18, 2025

Sometimes it is indeed necessary to wrap Rive in an outer Touchable or Pressable component.

Currently, clicking on Rive does not trigger the onPress of the outer Touchable or Pressable component.

I am temporarily using patch-package to add an onPress prop to RiveContainer and pass it to the inner TouchableWithoutFeedback for handling press events.

diff --git a/node_modules/rive-react-native/lib/typescript/Rive.d.ts b/node_modules/rive-react-native/lib/typescript/Rive.d.ts
index 2a22067..5309611 100644
--- a/node_modules/rive-react-native/lib/typescript/Rive.d.ts
+++ b/node_modules/rive-react-native/lib/typescript/Rive.d.ts
@@ -67,6 +67,7 @@ type RiveProps = {
     testID?: string;
 };
 type Props = {
+    onPress?: (event: GestureResponderEvent) => void;
     onPlay?: (animationName: string, isStateMachine: boolean) => void;
     onPause?: (animationName: string, isStateMachine: boolean) => void;
     onStop?: (animationName: string, isStateMachine: boolean) => void;
diff --git a/node_modules/rive-react-native/src/Rive.tsx b/node_modules/rive-react-native/src/Rive.tsx
index e5b95a9..1289cab 100644
--- a/node_modules/rive-react-native/src/Rive.tsx
+++ b/node_modules/rive-react-native/src/Rive.tsx
@@ -434,6 +434,7 @@ type RiveProps = {
 const VIEW_NAME = 'RiveReactNativeView';
 
 type Props = {
+  onPress?: (event: GestureResponderEvent) => void;
   onPlay?: (animationName: string, isStateMachine: boolean) => void;
   onPause?: (animationName: string, isStateMachine: boolean) => void;
   onStop?: (animationName: string, isStateMachine: boolean) => void;
@@ -467,6 +468,7 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
   (
     {
       children,
+      onPress,
       onPlay,
       onPause,
       onStop,
@@ -1022,6 +1024,7 @@ const RiveContainer = React.forwardRef<RiveRef, Props>(
       <View style={[styles.container, style]} ref={ref as any} testID={testID}>
         <View style={styles.children}>{children}</View>
         <TouchableWithoutFeedback
+          onPress={onPress}
           onPressIn={(event: GestureResponderEvent) =>
             touchBegan(event.nativeEvent.locationX, event.nativeEvent.locationY)
           }

Usage example:

<Pressable style={styles.touchable} onPress={handlePress}>
  <BackgroundSvg
    style={styles.background}
    fill="#FBD366"
    width={118}
    height={75}
  />
  {status === 'correct' ? (
    <CorrectSvg style={styles.resultIcon} />
  ) : status === 'wrong' ? (
    <WrongSvg style={styles.resultIcon} />
  ) : (
    <Rive
      ref={riveRef}
      style={styles.rive}
      url={riveAsset.uri}
      onPress={handlePress}
    />
  )}
</Pressable>

It is hoped that the final solution can define clickable areas within the Rive editor and trigger JS events, because Rive's Artboard often contains some blank spaces used for animation movement. Setting onPress for the entire Rive may cause users to trigger the button by clicking on surrounding blank areas.

I have tried adding a rectangle in the Rive editor to cover the expected clickable area and added a Listener (Pointer Down or Click), but the Rive component's onRiveEventReceived did not receive any related events.

@CacaoRick
Copy link

CacaoRick commented Jun 18, 2025

It is hoped that the final solution can define clickable areas within the Rive editor and trigger JS events, because Rive's Artboard often contains some blank spaces used for animation movement. Setting onPress for the entire Rive may cause users to trigger the button by clicking on surrounding blank areas.

I have tried adding a rectangle in the Rive editor to cover the expected clickable area and added a Listener (Pointer Down or Click), but the Rive component's onRiveEventReceived did not receive any related events.

After reviewing this: https://help.rive.app/runtimes/rive-events
I realized that by adding a trigger in the editor to report the event, you can achieve the specific area click event I need.
So, there’s no need patch-package to add onPress props.

<Rive
  ref={riveRef}
  style={styles.rive}
  url={riveAsset.uri}
  onRiveEventReceived={event => {
    if (event.name === 'on-press') {
      handlePress();
    }
  }}
/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants