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

Add screen transition animation #5274

Merged
merged 58 commits into from
Mar 25, 2024
Merged

Conversation

piaskowyk
Copy link
Member

@piaskowyk piaskowyk commented Oct 19, 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-screens 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

Copy link
Member

@tomekzaw tomekzaw left a comment

Choose a reason for hiding this comment

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

Left a couple of comments related mostly to code style.

src/reanimated2/screenTransition/swipeSimulator.ts Outdated Show resolved Hide resolved
src/reanimated2/screenTransition/swipeSimulator.ts Outdated Show resolved Hide resolved
app/src/examples/ScreenAnimationExample.tsx Outdated Show resolved Hide resolved
app/src/examples/ScreenAnimationExample.tsx Outdated Show resolved Hide resolved
app/src/examples/ScreenAnimationExample.tsx Outdated Show resolved Hide resolved
src/reanimated2/screenTransition/styleUpdater.ts Outdated Show resolved Hide resolved
src/reanimated2/screenTransition/swipeSimulator.ts Outdated Show resolved Hide resolved
src/reanimated2/screenTransition/swipeSimulator.ts Outdated Show resolved Hide resolved
src/reanimated2/screenTransition/swipeSimulator.ts Outdated Show resolved Hide resolved
src/reanimated2/screenTransition/swipeSimulator.ts Outdated Show resolved Hide resolved
@piaskowyk piaskowyk requested a review from tomekzaw March 7, 2024 14:12
Copy link
Member

@tomekzaw tomekzaw left a comment

Choose a reason for hiding this comment

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

🫡

app/src/examples/index.ts Outdated Show resolved Hide resolved
@piaskowyk piaskowyk added this pull request to the merge queue Mar 25, 2024
Merged via the queue into main with commit 6d93a90 Mar 25, 2024
7 checks passed
@piaskowyk piaskowyk deleted the @piaskowyk/screen-animations-swipe-back branch March 25, 2024 09:40
@Bayramito
Copy link

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

@anisurrahman072
Copy link

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"

@Bayramito
Copy link

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

@anisurrahman072
Copy link

@Bayramito
Copy link

Bayramito commented Apr 30, 2024

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

@anisurrahman072
Copy link

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

@Bayramito
Copy link

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

@anisurrahman072
Copy link

anisurrahman072 commented Apr 30, 2024

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

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.

None yet

6 participants