Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add screen "go back" transition animations based on gestures using Reanimated #1913

Merged
merged 82 commits into from
Jan 10, 2024

Conversation

WoLewicki
Copy link
Member

@WoLewicki WoLewicki commented Oct 5, 2023

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-reanimated repository: PR 1913.

Dependency requirements:

  • react-native-reanimated@3.6+
  • react-native-screens@3.28+
  • react-native-gesture-handler@2+

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

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.

5 participants