【问题标题】:React Navigation: Applying separate transitions to scenesReact Navigation:将单独的转换应用于场景
【发布时间】:2017-07-08 17:16:13
【问题描述】:

我想在我的 React Navigation 中的 StackNavigator 中为我的 React Native (iOS) 应用程序应用不同的转换。

export const AppNavigator = StackNavigator({
  Home: { screen: Home },
  NewChild: { screen: NewChild },
  Journal: { screen: Journal }
});

我可能希望 NewChild 像模态一样从下往上加载。或者我可能希望它从右向左滑入。如果可以定制,那就太好了。从文档来看,您似乎只能将您的 StackNavigation 设置为卡片或模式。

【问题讨论】:

  • 您可以使用自定义过渡器进行任何您想要的过渡。有几篇关于如何完成的好文章。我会尝试链接它们。
  • 这个问题,还定义了一个hack,你可以用它来为导航器中的每个屏幕实现不同的配置。 github.com/react-community/react-navigation/issues/707
  • 太棒了,谢谢你的链接!

标签: react-native react-navigation


【解决方案1】:

感谢线程中的每个人,它对我有用。

我有很多场景只由一个 StackNavigator 管理,我想为其中一些制作不同的动画。

首先,我在路由器中设置了一个常量,其中包括每个场景我想通过水平过渡显示:

const horizontalTransitionScenes = [
  AddContact,
];

之后,我用 StackNavigator 设计了我的应用路由器:

const App = StackNavigator({
  AddContact: {
    screen: AddContact,
  },
  EditContact: {
    screen: EditContact,
  },
});

我使用 CardStackStyleInterpolator 来修改场景之间的过渡。我可以这样导入:import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';

我们现在可以将 transitionConfig 参数添加到我们的 StackNavigator 以根据我们的场景显示不同的动画:

 const App = StackNavigator(
{
    AddContact: {
        screen: AddContact
    },
    EditContact: {
        screen: EditContact
    }
},
{
    transitionConfig: (currentState: any) => {
        if (
            currentState.scenes[
                currentState.scenes.length - 1
            ].route.routeName.includes(horizontalTransitionScenes)
        ) {
            return {
                screenInterpolator: CardStackStyleInterpolator.forHorizontal
            };
        }
        return {
            screenInterpolator: CardStackStyleInterpolator.forVertical
        };
    }
}
);

使用 StackNavigator 实现,您将能够为您想要的场景显示不同类型的动画。

祝你有美好的一天?

【讨论】:

    【解决方案2】:

    正如您在文档中看到的那样,现在不可能。您可以跟踪请求此功能的this issuethis issue。它位于roadmap for v2,但由于 v1 尚未发布,您最好的选择可能是:

    1. 实现您自己的transitionConfig,以某种方式处理每个屏幕的问题。我不确定这是否可行。
    2. 使用来自main issue 的想法来实现一些东西。或者简单地使您的 fork 特定于您的代码并维护它,直到该问题得到解决。

    【讨论】:

    • 知道了。感谢迈克尔的回复。
    【解决方案3】:

    我能够通过执行一些条件逻辑来实现这一点,我们在 react-navigation 3.3.2

    您必须从react-native 导入EasingAnimated,然后您可以按名称或按索引(以下是按名称)有条件地为特定屏幕渲染过渡。

    通过在导航器之外声明配置,并用{} 切换transitionSpec,它只会在该特定屏幕上触发——与screenInterpolator 的条件相同。

    Screen1Screen2 有动画,但其他屏幕都没有动画。

    const screen2Config = {
      duration: 300,
      easing: Easing.out(Easing.poly(4)),
      timing: Animated.timing,
    };
    
    export const ScreenStack = createStackNavigator({
      Screen1: {
        screen: Screen1,
        navigationOptions: ({ navigation }) => ({
          headerTitle: 'Screen1',
          headerTitleAllowFontScaling: false,
        }),
      },
      Screen2: {
        screen: Screen2,
        navigationOptions: ({ navigation }) => ({
          headerTitle: 'Screen2',
          headerTitleAllowFontScaling: false,
          tabBarVisible: false,
        }),
      },
      Screen3: {
        screen: Screen3,
        navigationOptions: ({ navigation }) => ({
          headerTitle: 'Screen3',
          headerTitleAllowFontScaling: false,
        }),
      },
      Screen4: {
        screen: Screen4,
        navigationOptions: ({ navigation }) => ({
          headerTitle: 'Screen4',
          headerTitleAllowFontScaling: false,
        }),
      },
    }, {
      headerMode: 'float',
      mode: 'modal',
      transitionConfig: sceneProps => ({
        transitionSpec: sceneProps.scene.route.routeName === 'Screen2' ? screen2Config : {},
        screenInterpolator: (sceneProps) => {
          if (sceneProps.scene.route.routeName === 'Screen2') {
            const { layout, position, scene } = sceneProps;
            const { index } = scene;
    
            const width = layout.initWidth;
            const translateX = position.interpolate({
              inputRange: [index - 1, index, index + 1],
              outputRange: [width, 0, 0],
            });
    
            const opacity = position.interpolate({
              inputRange: [index - 1, index - 0.99, index],
              outputRange: [0, 1, 1],
            });
    
            return { opacity, transform: [{ translateX }] };
          }
        },
      }),
    });
    

    【讨论】:

      猜你喜欢
      • 2017-04-19
      • 2018-10-29
      • 2017-05-23
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 2019-04-13
      • 1970-01-01
      相关资源
      最近更新 更多