当前位置:   article > 正文

React-Native: 页面搭建,导航配置_创建一个reactnative 反映导航项目

创建一个reactnative 反映导航项目

第一步:安装

npm i @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/native-stack @react-navigation/bottom-tabs

如果是iOS上跑程序,就需要重新去pod install,把上面新增的库,下载到工程本地 

第二步:配置

1、如图所示,在 src/pages 目录下,

新建 index.js --- 用来导出所有页面

新建tabBar/Home.js --- 项目首页

新建 My.js --- 项目个人中心页

新建 TabBarNavigator.js --- 配置tabBar页面

新建 launchPage/LaunchPage.js --- 项目启动页

新建 launchPage/GuidePage.js --- 项目引导页

2、编写index.js

  1. import LaunchPage from './launchPage/LaunchPage';
  2. import GuidePage from './launchPage/GuidePage';
  3. import Home from './tabBar/Home';
  4. import My from './tabBar/My';
  5. import TabBarNavigator from './tabBar/TabBarNavigator';
  6. const appRouter = [
  7. {
  8. name: 'LaunchPage',
  9. component: LaunchPage,
  10. headerShown: false,
  11. },
  12. {
  13. name: 'GuidePage',
  14. component: GuidePage,
  15. headerShown: false,
  16. },
  17. {
  18. name: 'Home',
  19. component: Home,
  20. headerShown: false,
  21. },
  22. {
  23. name: 'My',
  24. component: My,
  25. headerShown: false,
  26. },
  27. {
  28. name: 'TabBarNavigator',
  29. component: TabBarNavigator,
  30. headerShown: false,
  31. },
  32. ];
  33. export default appRouter;

注意name和component名字可以不一样,但是后续 navigation 的页面跳转都是用 name,以免造成开发上面的心智困难,建议弄成一样,不然后续你看着页面文件想不起页面的name命名。。。

3、修改App.js

Provider 是全局状态管理redux --- 不需要可以去掉

AntdProvider 是@ant-design/react-native的Provider自定义重命名,有的这个东西antd的一些弹窗才能显示 --- 不需要可以去掉

  1. import React from 'react';
  2. import {StyleSheet} from 'react-native';
  3. import {NavigationContainer} from '@react-navigation/native';
  4. import {createNativeStackNavigator} from '@react-navigation/native-stack';
  5. import {
  6. SafeAreaProvider,
  7. initialWindowMetrics,
  8. } from 'react-native-safe-area-context';
  9. import {Provider} from 'react-redux';
  10. import {Provider as AntdProvider} from '@ant-design/react-native';
  11. import appRouter from 'src/pages';
  12. import store from 'src/redux/store';
  13. const Stack = createNativeStackNavigator();
  14. export default function App() {
  15. console.log(appRouter);
  16. return (
  17. <Provider store={store}>
  18. <AntdProvider>
  19. <SafeAreaProvider initialMetrics={initialWindowMetrics}>
  20. <NavigationContainer>
  21. <Stack.Navigator initialRouteName={'LaunchPage'}>
  22. {appRouter &&
  23. appRouter.map(item => {
  24. return (
  25. <Stack.Screen
  26. key={item.name}
  27. name={item.name}
  28. component={item.component}
  29. options={{headerShown: item.headerShown}}
  30. />
  31. );
  32. })}
  33. </Stack.Navigator>
  34. </NavigationContainer>
  35. </SafeAreaProvider>
  36. </AntdProvider>
  37. </Provider>
  38. );
  39. }
  40. const styles = StyleSheet.create({});

此处我的默认页面为 LaunchPage 就启动App 进入首页前,必须经过 LaunchPage页面。

在LaunchPage页面初始化一些App数据很有必要。

如果说后续配置了App的启动图,再到我们页面的启动页会显示两张,解决方法也很简单,就是将App的启动图和我们页面的启动页图设置成同一张图即可

4、 编写LaunchPage.js

  1. import React, {useEffect} from 'react';
  2. import {NativeModules, Platform, StatusBar, View} from 'react-native';
  3. import {useNavigation} from '@react-navigation/native';
  4. import {commonSize, commonStyle} from 'src/assets/css/commonStyle';
  5. import {storageSync} from 'src/utils/storage';
  6. import {navigateReplace, setNavigation} from 'src/utils/navigation';
  7. import {useSafeAreaInsets} from 'react-native-safe-area-context';
  8. import {CtImage} from 'src/components';
  9. import Orientation from '@hortau/react-native-orientation-locker';
  10. const LaunchPage = () => {
  11. // 给 navigation.js 传递 navigation
  12. const navigation = useNavigation();
  13. setNavigation(navigation);
  14. const insets = useSafeAreaInsets();
  15. // 获取状态栏高度
  16. const {StatusBarManager} = NativeModules;
  17. if (Platform.OS === 'ios') {
  18. commonSize.statusBarHeight = StatusBarManager.HEIGHT;
  19. } else if (Platform.OS === 'android') {
  20. commonSize.statusBarHeight =
  21. (StatusBarManager && StatusBarManager.HEIGHT) || StatusBar.currentHeight;
  22. }
  23. // 获取iOS安全区域距离
  24. // 注意 iOS的状态栏高度 与 iOS的顶部安全距离 不一定一样高
  25. // 在布局特殊全面屏头部的时候 建议使用 iOS的顶部安全距离
  26. if (Platform.OS === 'ios') {
  27. commonSize.safeAreaInsetTop = insets.top;
  28. commonSize.safeAreaInsetBottom = insets.bottom;
  29. commonSize.safeAreaInsetLeft = insets.left;
  30. commonSize.safeAreaInsetRight = insets.right;
  31. }
  32. // 获取当前设备的方向
  33. commonSize.screenOrientation = Orientation.getInitialOrientation();
  34. useEffect(() => {
  35. // 判断用户是否是第一层启动App 是则进入引导页 否则进入首页
  36. setTimeout(async () => {
  37. let isFirstLaunchApp = await storageSync.getStorage('isFirstLaunchApp');
  38. if (Number(isFirstLaunchApp) === 1) {
  39. goHome();
  40. } else {
  41. goGuide();
  42. }
  43. }, 1000);
  44. }, []);
  45. const goHome = () => {
  46. navigateReplace('TabBarNavigator');
  47. };
  48. return (
  49. <View style={commonStyle.container}>
  50. <CtImage source={require('src/assets/images/img_launchPage.jpg')} />
  51. </View>
  52. );
  53. };
  54. export default LaunchPage;

5、编写GuidePage.js

  1. import React, {useState} from 'react';
  2. import {StyleSheet, View} from 'react-native';
  3. import {CustomSwiper, CtBtn} from 'src/components';
  4. import {commonStyle} from 'src/assets/css/commonStyle';
  5. import {navigateReplace} from 'src/utils/navigation';
  6. import {storageSync} from 'src/utils/storage';
  7. const GuidePage = () => {
  8. const [swiperCurrentIndex, setSwiperCurrentIndex] = useState(0);
  9. const guideList = [
  10. {
  11. image_url: require('src/assets/images/img_GuidePage01.jpg'),
  12. name: '001',
  13. },
  14. {
  15. image_url: require('src/assets/images/img_GuidePage02.jpg'),
  16. name: '002',
  17. },
  18. {
  19. image_url: require('src/assets/images/img_GuidePage03.jpg'),
  20. name: '003',
  21. },
  22. ];
  23. const getSwiperChange = item => {
  24. setSwiperCurrentIndex(item.index);
  25. };
  26. const guideSwiperMask = () => {
  27. if (swiperCurrentIndex === guideList.length - 1) {
  28. return (
  29. <View style={[commonStyle.flexCenter, styles.swiperMaks]}>
  30. <CtBtn
  31. btnText={"Let's go"}
  32. onPress={() => {
  33. storageSync.setStorage('isFirstLaunchApp', 1);
  34. navigateReplace('TabBarNavigator');
  35. }}
  36. />
  37. </View>
  38. );
  39. } else {
  40. return <View style={styles.swiperMaks} />;
  41. }
  42. };
  43. return (
  44. <View style={styles.container}>
  45. <CustomSwiper
  46. onSwiperChange={getSwiperChange}
  47. data={guideList}
  48. autoplay={false}
  49. />
  50. {guideSwiperMask(guideList)}
  51. </View>
  52. );
  53. };
  54. export default GuidePage;
  55. const styles = StyleSheet.create({
  56. container: {
  57. flex: 1,
  58. },
  59. swiperMaks: {
  60. position: 'absolute',
  61. left: 0,
  62. right: 0,
  63. bottom: 60,
  64. },
  65. });

这个页面就是一个轮播图,轮播到最后一张引导图的时候,显示一个按钮,点击按钮,进入首页

6、编写TabBarNavigator.js

  1. import React from 'react';
  2. import {StyleSheet, Image} from 'react-native';
  3. import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
  4. import {commonColors} from 'src/assets/css/commonStyle';
  5. import Home from './Home';
  6. import My from './My';
  7. const Tab = createBottomTabNavigator();
  8. const TabBarNavigator = () => {
  9. return (
  10. <Tab.Navigator
  11. initialRouteName={Home}
  12. screenOptions={{
  13. tabBarHideOnKeyboard: true,
  14. tabBarInactiveTintColor: commonColors.textColorSecondary,
  15. tabBarActiveTintColor: commonColors.textColorPrimary,
  16. tabBarStyle: styles.tabBarStyle,
  17. }}>
  18. <Tab.Screen
  19. name={'Home'}
  20. component={Home}
  21. options={{
  22. headerShown: false,
  23. tabBarIcon: ({focused}) => (
  24. <Image
  25. style={styles.tabBarIcon}
  26. source={
  27. focused
  28. ? require('src/assets/images/tabBar/tab_home_active.png')
  29. : require('src/assets/images/tabBar/tab_home.png')
  30. }
  31. />
  32. ),
  33. }}
  34. />
  35. <Tab.Screen
  36. name={'My'}
  37. component={My}
  38. options={{
  39. headerShown: false,
  40. tabBarIcon: ({focused}) => (
  41. <Image
  42. style={styles.tabBarIcon}
  43. source={
  44. focused
  45. ? require('src/assets/images/tabBar/tab_my_active.png')
  46. : require('src/assets/images/tabBar/tab_my.png')
  47. }
  48. />
  49. ),
  50. }}
  51. />
  52. </Tab.Navigator>
  53. );
  54. };
  55. export default TabBarNavigator;
  56. const styles = StyleSheet.create({
  57. tabBarStyle: {
  58. backgroundColor: commonColors.bgColorWhite,
  59. },
  60. tabBarIcon: {
  61. resizeMode: 'cover',
  62. width: 28,
  63. height: 28,
  64. },
  65. });

 7、上面的代码里面,我重新封装了navigation。在 src/utils 下 新建navigation.js

  1. import React from 'react';
  2. import {StackActions} from '@react-navigation/native';
  3. import indexConfig from 'src/config/index.config';
  4. let _navigation;
  5. function setNavigation(navigation) {
  6. _navigation = navigation;
  7. }
  8. const navigatePush = (routeName, params) => {
  9. _navigation.dispatch(StackActions.push(routeName, params));
  10. };
  11. const navigateReplace = (routeName, params) => {
  12. _navigation.dispatch(StackActions.replace(routeName, params));
  13. };
  14. const navigateBack = (count = 1) => {
  15. _navigation.dispatch(StackActions.pop(count));
  16. };
  17. const navigateToTop = () => {
  18. _navigation.dispatch(StackActions.popToTop());
  19. };
  20. const authNavigatePush = (routeName, params) => {
  21. let accessToken = indexConfig.accessToken;
  22. if (accessToken) {
  23. navigatePush(routeName, params);
  24. } else {
  25. navigatePush('Login', params);
  26. }
  27. };
  28. const authNavigateReplace = (routeName, params) => {
  29. let accessToken = indexConfig.accessToken;
  30. if (accessToken) {
  31. navigateReplace(routeName, params);
  32. } else {
  33. navigatePush('Login', params);
  34. }
  35. };
  36. export {
  37. setNavigation,
  38. navigatePush,
  39. navigateReplace,
  40. navigateBack,
  41. navigateToTop,
  42. authNavigatePush,
  43. authNavigateReplace,
  44. };

在 LaunchPage 页面 调用 setNavigation(navigation); 把 useNavigation hock方法传进来,

这样以来,就不用在每个页面去写 useNavigation。并且 新增了 authNavigatePush 等方法,可以简单判断用户是否登录。

8、此外,贴上我的 src/assets/css/commonStyle.js

  1. import {Dimensions, Platform, StatusBar, StyleSheet} from 'react-native';
  2. const {width, height} = Dimensions.get('window');
  3. const commonColors = {
  4. colorPrimary: '#FFD200',
  5. colorPrimaryRgba: 'rgba(255, 210, 0, 0.2)',
  6. colorSuccess: '#07c160',
  7. colorWarning: '#F59A23',
  8. colorDanger: '#ee0a24',
  9. colorInfo: '#fffbe8',
  10. bgColorBlack: '#000',
  11. bgColorWhite: '#fff',
  12. bgColorPrimary: '#F5F5F5',
  13. bgColorTransparent: 'transparent',
  14. textColorPrimary: '#333',
  15. textColorRegular: '#666',
  16. textColorSecondary: '#999',
  17. textColorPlaceholder: '#E0E0E0',
  18. borderColorBase: '#AAA',
  19. borderColorDark: '#999',
  20. borderColorLight: '#E5E5E5',
  21. borderColorLighter: '#E0E0E0',
  22. };
  23. const commonSize = {
  24. screenOrientation: '',
  25. width: width,
  26. height: height,
  27. statusBarHeight: 0,
  28. safeAreaInsetTop: 0,
  29. safeAreaInsetBottom: 0,
  30. safeAreaInsetLeft: 0,
  31. safeAreaInsetRight: 0,
  32. navBarHeight: 44,
  33. radiusMedium: 12,
  34. radiusSmall: 8,
  35. radiusMini: 4,
  36. borderWidth: StyleSheet.hairlineWidth,
  37. };
  38. const commonStyle = {
  39. /** flex **/
  40. flexLeftCenter: {
  41. flexDirection: 'row',
  42. alignItems: 'center',
  43. },
  44. flexCenter: {
  45. flexDirection: 'row',
  46. alignItems: 'center',
  47. justifyContent: 'center',
  48. },
  49. flexRightCenter: {
  50. flexDirection: 'row',
  51. alignItems: 'center',
  52. justifyContent: 'flex-end',
  53. },
  54. flexBetween: {
  55. flexDirection: 'row',
  56. alignItems: 'center',
  57. justifyContent: 'space-between',
  58. },
  59. flexColumnLeft: {
  60. flexDirection: 'column',
  61. alignItems: 'flex-start',
  62. },
  63. flexColumnCenter: {
  64. flexDirection: 'column',
  65. alignItems: 'center',
  66. justifyContent: 'center',
  67. },
  68. flexColumnRight: {
  69. flexDirection: 'column',
  70. alignItems: 'flex-end',
  71. },
  72. flexColumnBetween: {
  73. flexDirection: 'column',
  74. justifyContent: 'space-between',
  75. },
  76. flexAround: {
  77. flexDirection: 'row',
  78. justifyContent: 'space-around',
  79. },
  80. flexWrap: {
  81. flexDirection: 'row',
  82. flexWrap: 'wrap',
  83. },
  84. testBorder: {
  85. borderWidth: 5,
  86. borderColor: 'red',
  87. },
  88. bgFFF: {
  89. backgroundColor: commonColors.bgColorWhite,
  90. },
  91. bg000: {
  92. backgroundColor: commonColors.bgColorBlack,
  93. },
  94. container: {
  95. flex: 1,
  96. position: 'relative',
  97. backgroundColor: commonColors.bgColorPrimary,
  98. },
  99. relative: {
  100. position: 'relative',
  101. },
  102. absolute: {
  103. position: 'absolute',
  104. },
  105. };
  106. export {commonColors, commonSize, commonStyle};
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/543840
推荐阅读
相关标签
  

闽ICP备14008679号