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

ja1ns pushed a commit to WiseOwlTech/react-native-screens that referenced this pull request Oct 9, 2024
## 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](software-mansion/react-native-reanimated#5274).

## Test plan

Test example from Example App

---------

Co-authored-by: Krzysztof Piaskowy <krzysztof.piaskowy@swmansion.com>
ja1ns pushed a commit to WiseOwlTech/react-native-screens that referenced this pull request Oct 9, 2024
…nsion#2017)

## Description

Unfortunately, because of changing the way how we export the components,
I didn't saw the wrong export of GHContext in gesture-handler's
`index.tsx` file. To match the changes from the PR with full screen
swipe (software-mansion#1913), I've created the directory in a wrong place. This PR
fixes this export by moving the context to native-stack and removing the
export from the gesture-handler/index.tsx.
I'm also removing this export, because right now it's possible to import
GHContext from `react-native-screens` and also from
`react-native-screens/gesture-handler` which is wrong.

## Changes

- Changed the export of GHContext in index.tsx
- Moved GHContext from gesture-handler to native-stack

## Test code and steps to reproduce

Try to build and run TestsExample - see if the bundling state passes
correctly. Then, try to import GestureDetectorProvider and wrap whole
navigator in it.

## Checklist

- [X] Included code example that can be used to test this change
- [x] Ensured that CI passes
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