React Navigation V3在转到另一个页面时处理转换和动画

问题描述 投票:2回答:1

我目前正在使用最新的react-navigation-v3。我试过这个solution。但它对我没有用。

这是我尝试从链接中的解决方案复制的过渡。

const Transition = (index, position) => {
    const inputRange = [index - 1, index, index + 1];
    const opacity = position.interpolate({
        inputRange,
        outputRange: [.8, 1, 1],
    });

    const scaleY = position.interpolate({
        inputRange,
        outputRange: ([0.8, 1, 1]),
    });

    return {
        opacity,
        transform: [
            {scaleY}
        ]
    };
};

这是我宣布的transitionConfig

const TransitionConfiguration = () => {
    return {
        // Define scene interpolation, eq. custom transition
        screenInterpolator: (sceneProps) => {

            const {position, scene} = sceneProps;
            const {index, route} = scene
            const params = route.params || {}; // <- That's new
            const transition = params.transition || 'default'; // <- That's new

            return {
                transition: Transition(index, position),
                default: Transition(index, position),
            }[transition];
        }
    }
};

以下是所有路线列表:

const UnauthenticatedScreens = createStackNavigator(
    { // Screens
        Login: { screen: Login }
    }
);


const AuthenticatedInitialScreens = createStackNavigator(
    { // Screens
        Home: {
            screen: Home
        },
    }, { // Default options
        defaultNavigationOptions: ({ navigation }) => {
            return {
                header:
                    <DrawerHeader // Default header component
                        headerTitle={navigation.state.routeName}
                        icon="menu"
                        onPress={() => navigation.openDrawer()}
                    />
            };
        }
    }
);

const AppDrawerNavigator = createDrawerNavigator(
    { // Screens
        Home: AuthenticatedInitialScreens,
    }, { // Default options
        initialRouteName: 'Home',
        contentComponent: DrawerComponent, // Default drawer component
        contentOptions: {
            activeTintColor: COLOR.PANTOME
        }
    }
);

const AppSwitchNavigator = createSwitchNavigator(
    { // Screens
        Splash: { screen: Splash },
        UnauthenticatedScreens: { screen: UnauthenticatedScreens },
        AuthenticatedInitialScreens: { screen: AppDrawerNavigator }
    }, { // Default options
        initialRouteName: 'Splash',
        transitionConfig: TransitionConfiguration
    }
);

const AppContainer = createAppContainer(AppSwitchNavigator);

export default AppContainer

componentDidMount方法的我的Splash组件中。

componentDidMount() {
        this.props.actions.restoreSession();
        setTimeout(() => {
            this.props.state.isAuth
                ? this.props.navigation.navigate({
                    params: {
                        transition: 'transition'
                    }
                })
                : this.props.navigation.navigate({
                    routeName: 'UnauthenticatedScreens',
                    params: {
                        transition: 'transition'
                    }
                })
        }, 2000);
    }

感谢有人可以提供帮助。提前致谢。

reactjs react-native animation transition react-navigation
1个回答
0
投票

我能够通过做一些条件逻辑来完成这个,我们在react-navigation 3.3.2。也

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

通过在导航器外声明配置,并使用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 }] };
      }
    },
  }),
});
© www.soinside.com 2019 - 2024. All rights reserved.