decebal
decebal

Reputation: 1211

Custom animation for React Native Stack navigation

I need to create a custom animation effect, which is pretty similar with the default one on iOS, but with a small difference: When I change the screen, I need the next screen to push the current screen to the left. The default animation is placing the next screen over the current one and it also moves the current screen to the left. But I need the next screen to literally push the current screen because I have a wave which starts from the first screen and continues to the second screen and I would like to achieve a continuation effect when changing the screens.

This is what I have for now, but it is just hiding the current screen on screen change:

<Stack.Navigator 
    initialRouteName="Language"
    screenOptions={{
        cardOverlayEnabled: true,
        gestureEnabled: true,
        ...MyTransition,
}}>
...
</Stack.Navigator>
const MyTransition = {
    gestureDirection: 'horizontal',
    transitionSpec: {
      open: TransitionSpecs.TransitionIOSSpec,
      close: TransitionSpecs.TransitionIOSSpec,
    },
    cardStyleInterpolator: ({ current, next, layouts }) => {
      return {
        cardStyle: {
          transform: [
            {
              translateX: current.progress.interpolate({
                inputRange: [0, 1],
                outputRange: [layouts.screen.width, 0],
              }),
            },
          ],
        },
      };
    },
};

Thanks for your help!

Upvotes: 0

Views: 1869

Answers (1)

Bence
Bence

Reputation: 63

I just coming across this issue and i think i find the solution on react navigation official site.

const cardStyleInterpolator = ({
  current,
  next,
  inverted,
  layouts: { screen }
}) => {
  const progress = Animated.add(
    current.progress.interpolate({
      inputRange: [0, 1],
      outputRange: [0, 1],
      extrapolate: "clamp"
    }),
    next
      ? next.progress.interpolate({
          inputRange: [0, 1],
          outputRange: [0, 1],
          extrapolate: "clamp"
        })
      : 0
  );

  return {
    cardStyle: {
      transform: [
        {
          translateX: Animated.multiply(
            progress.interpolate({
              inputRange: [0, 1, 2],
              outputRange: [
                screen.width, // Focused, but offscreen in the beginning
                0, // Fully focused
                //I changed this line only
                //screen.width * -0.3 // Fully unfocused
                -screen.width
              ],
              extrapolate: "clamp"
            }),
            inverted
          )
        }
      ]
    }
  };
};

https://reactnavigation.org/docs/stack-navigator

Usage:

<Stack.Navigator
  screenOptions={{
    headerShown: false, //Optional
    cardStyle: { backgroundColor: "transparent" }, //Optional
    cardStyleInterpolator
  }}
>
  <Stack.Screen name="ScreenA" component={ScreenA} />
  <Stack.Screen name="ScreenB" component={ScreenB} />
</Stack.Navigator>

Upvotes: 1

Related Questions