首页 > 解决方案 > 如何在带有 react-navigation 的屏幕之间拥有不同的过渡动画?

问题描述

我目前正在开发一个ReactNative有 2 个屏幕的应用程序。目标是为屏幕设置动画,使它们根据您来自哪个屏幕上下相互推动。以下GIF是我想要实现的过渡。

我正在寻找的过渡示例

目前我正在使用createAnimatedSwitchNavigator来创建效果,问题是我当前的过渡只会将屏幕向上推。有没有办法在动画切换导航器中检测我当前在哪个屏幕上,以便我可以改变过渡的方向?

const MySwitch = createAnimatedSwitchNavigator(
  {
    Home: {
        screen: Home
    },
    Page2: {
        screen: Page2
    },
  },
  {
    transition: (
        <Transition.Together>
            <Transition.Out
                type="slide-top"
                durationMs={400}
                interpolation="easeIn"
            />
            <Transition.In type="slide-bottom" durationMs={500} />
        </Transition.Together>
    )
  }
);

请指导我。

谢谢

标签: react-nativereact-navigationexporeact-native-reanimated

解决方案


做了一些研究,并能够使用以下代码使其工作:

const AppNavigator = createStackNavigator({
    Home: {
        screen: Home
    },
    Page2: {
        screen: Page2
    }
},
{
    initialRouteName: "Home",
    headerMode: "none",
    defaultNavigationOptions: {
        gesturesEnabled: false
    },
    transitionConfig: () => ({
        transitionSpec: {
          duration: 1400,
          easing: Easing.out(Easing.poly(4)),
          timing: Animated.timing,
        },
        screenInterpolator: sceneProps => {
          const { layout, position, scene } = sceneProps;
          const { index } = scene;

          const height = layout.initHeight;
          const translateY = position.interpolate({
            inputRange: [index - 1, index, index + 1],
            outputRange: [height, 0, -height],
          });

          const opacity = position.interpolate({
            inputRange: [index - 1, index - 0.99, index],
            outputRange: [0, 1, 1],
          });

          return { opacity, transform: [{ translateY }] };
        },
      }),
});

最难的部分是理解插值,因为似乎有很多看似任意的值。我没有找到最好的文档,但是能够得出以下理解:

以下面的代码为例。这里的第一件事是设置翻译的类型,在这种情况下是translateY

const translateY = position.interpolate({
            inputRange: [index - 1, index, index + 1],
            outputRange: [height, 0, -height],
          });

下一个令人困惑的部分是输入和输出范围,这些数字是什么意思?那么输入范围实际上映射到输出范围。看起来像这样:

inputRange: [newScreen, currentScreen, previousScreen]

在 inputRange 中我们指定我们想要动画的屏幕,然后在 output range 我们指定我们想要对这些屏幕做什么。修改outputRange[0]会修改 newScreen 等。

由于我们已经将翻译类型设置为translateY我们知道屏幕正在向上或向下移动。

outputRange: [height, 0, -height]

这现在告诉新屏幕向上移动到屏幕顶部,并且旧屏幕也向上移动,超出屏幕顶部(因此 -height,与 CSS 中的 -100vh 相同)。


推荐阅读