react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Add screen transition animation

Open piaskowyk opened this issue 8 months ago • 1 comments

Summary

This pull request introduces a new feature which adds screen "go back" transition animations based on gestures. The feature is a collaboration between three libraries: react-native-reanimated, react-native-screens, and react-native-gesture-handler. Implementing this feature required changes in both Reanimated and RNScreens. You can find the related pull request in the react-native-screens repository: PR 1913.

Dependency requirements:

A demo of this feature was presented at the RNCK meetup: RNCK Meetup Demo

API Overview

Basic usage

To use this feature, you need to import the GestureDetectorProvider from react-native-screens/gesture-handler and wrap your navigation container with it. Here's an example:

import { GestureDetectorProvider } from 'react-native-screens/gesture-handler';

<GestureHandlerRootView>
  <NavigationContainer>
    <GestureDetectorProvider>
      <Stack.Navigator
        screenOptions={{
          stackAnimation: 'none',
        }}>
        <Stack.Screen
          name="ScreenA"
          component={ScreenA}
        />
        <Stack.Screen
          name="ScreenB"
          component={ScreenB}
          options={{
            goBackGesture: 'swipeRight', // gestures that trigger the screen transition
          }}
        />
      </Stack.Navigator>
    </GestureDetectorProvider>
  </NavigationContainer>
</GestureHandlerRootView>

Available gestures:

  • swipeRight
  • swipeLeft
  • swipeUp
  • swipeDown
  • verticalSwipe
  • horizontalSwipe
  • twoDimensionalSwipe

Preset usage

You can also use preset animations for the transition. Import ScreenTransition from react-native-reanimated and specify the desired preset in the transitionAnimation option. Example:

import { ScreenTransition } from 'react-native-reanimated';

<Stack.Screen
  name="ScreenB"
  component={ScreenB}
  options={{
    goBackGesture: 'swipeRight',
    transitionAnimation: ScreenTransition.SwipeRightFade, // transition preset
  }}
/>

Available presets:

  • SwipeRight
  • SwipeLeft
  • SwipeDown
  • SwipeUp
  • Horizontal
  • Vertical
  • TwoDimensional
  • SwipeRightFade

You don't need to worry about the preset because each gesture is associated with a default transition preset.

Custom Animation

If you want to create a custom animation, you can define your own AnimatedScreenTransition object. Here's an example:

const customTransition: AnimatedScreenTransition = {
  topScreenFrame: (event, screenSize) => {
    'worklet';
    const progress = event.translationX / screenSize.width;
    return {
      transform: [
        { translateX: 1.3 * event.translationX },
        { rotate: 20 * progress + 'deg' }
      ]
    };
  },
  belowTopScreenFrame: (event, screenSize) => {
    'worklet';
    const progress = event.translationX / screenSize.width;
    return {
      transform: [
        { scale: 0.7 + 0.3 * progress }
      ]
    };
  },
}

<Stack.Screen
  name="ScreenB"
  component={ScreenB}
  options={{
    goBackGesture: 'swipeRight',
    transitionAnimation: customTransition
  }}
/>

screenEdgeGesture

To trigger a gesture that starts from the edge of the screen, you can use the screenEdgeGesture option. Example:

<Stack.Screen
  name="ScreenB"
  component={ScreenB}
  options={{
    goBackGesture: 'swipeRight',
    screenEdgeGesture: true
  }}
/>

This means you can trigger a transition with a gesture that starts from the edge of the screen.

Test plan

Test example from Example App

piaskowyk avatar Oct 19 '23 09:10 piaskowyk

Very useful PR! Would it be possible to add an array with multiple gesture presets? This would let you go back from multiple directions, like what AirBnb allows when viewing a listing.

nandorojo avatar Jan 15 '24 20:01 nandorojo

Is this feature working with the current versions of RNGH and Reanimated ?

Bayramito avatar Mar 29 '24 08:03 Bayramito

Is this feature working with the current versions of RNGH and Reanimated ?

Nope @Bayramito. It is currently only available in "react-native-reanimated": "3.9.0-rc.0"

anisurrahman072 avatar Apr 13 '24 21:04 anisurrahman072

Could not make it work with the latest versions of Scresns, Reanimated and GH

Bayramito avatar Apr 30 '24 09:04 Bayramito

  • Hi @Bayramito, please check the version change log that you are using. Is that 3.9.0? As per 3.9.0, I see https://github.com/software-mansion/react-native-reanimated/pull/5274 has been added already 🚀

anisurrahman072 avatar Apr 30 '24 09:04 anisurrahman072

Hey, yes it's 3.9.0. I was waiting for official release to test this feature...

Bayramito avatar Apr 30 '24 09:04 Bayramito

I didn't try with 3.9.0 but I tried with 3.9.0-rc.0 (pre release of 3.9). It worked pretty smoothly 🚀

Let's try it on 3.9.0-rc.0. If it works then you can move to 3.9.0 (Latest).

✅ If you want then you can follow my guide on this here (Link: https://github.com/anisurrahman072/React-Native-SDK-Research/blob/master/ReactNativeScreen3.30.md)

Full output is here too: https://x.com/anis_RNCore/status/1778968599597899891

anisurrahman072 avatar Apr 30 '24 09:04 anisurrahman072

Well I just spot my issue. I was importing the createNativeStackNavigator from @react-navigation instead of react-native-screens. But now i got this error

simulator_screenshot_932DD1AE-12DC-49BA-94CC-66D7BC0D78C1

Bayramito avatar Apr 30 '24 10:04 Bayramito

Amazing 🚀. But it would be great if you create a separate discussion or ISSUE mate, as it seems a good discussion 💯

anisurrahman072 avatar Apr 30 '24 14:04 anisurrahman072