赞
踩
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
- import LaunchPage from './launchPage/LaunchPage';
- import GuidePage from './launchPage/GuidePage';
- import Home from './tabBar/Home';
- import My from './tabBar/My';
- import TabBarNavigator from './tabBar/TabBarNavigator';
-
- const appRouter = [
- {
- name: 'LaunchPage',
- component: LaunchPage,
- headerShown: false,
- },
- {
- name: 'GuidePage',
- component: GuidePage,
- headerShown: false,
- },
- {
- name: 'Home',
- component: Home,
- headerShown: false,
- },
- {
- name: 'My',
- component: My,
- headerShown: false,
- },
- {
- name: 'TabBarNavigator',
- component: TabBarNavigator,
- headerShown: false,
- },
- ];
-
- export default appRouter;
注意name和component名字可以不一样,但是后续 navigation 的页面跳转都是用 name,以免造成开发上面的心智困难,建议弄成一样,不然后续你看着页面文件想不起页面的name命名。。。
3、修改App.js
Provider 是全局状态管理redux --- 不需要可以去掉
AntdProvider 是@ant-design/react-native的Provider自定义重命名,有的这个东西antd的一些弹窗才能显示 --- 不需要可以去掉
- import React from 'react';
- import {StyleSheet} from 'react-native';
- import {NavigationContainer} from '@react-navigation/native';
- import {createNativeStackNavigator} from '@react-navigation/native-stack';
- import {
- SafeAreaProvider,
- initialWindowMetrics,
- } from 'react-native-safe-area-context';
- import {Provider} from 'react-redux';
- import {Provider as AntdProvider} from '@ant-design/react-native';
- import appRouter from 'src/pages';
- import store from 'src/redux/store';
-
- const Stack = createNativeStackNavigator();
-
- export default function App() {
- console.log(appRouter);
- return (
- <Provider store={store}>
- <AntdProvider>
- <SafeAreaProvider initialMetrics={initialWindowMetrics}>
- <NavigationContainer>
- <Stack.Navigator initialRouteName={'LaunchPage'}>
- {appRouter &&
- appRouter.map(item => {
- return (
- <Stack.Screen
- key={item.name}
- name={item.name}
- component={item.component}
- options={{headerShown: item.headerShown}}
- />
- );
- })}
- </Stack.Navigator>
- </NavigationContainer>
- </SafeAreaProvider>
- </AntdProvider>
- </Provider>
- );
- }
-
- const styles = StyleSheet.create({});
此处我的默认页面为 LaunchPage 就启动App 进入首页前,必须经过 LaunchPage页面。
在LaunchPage页面初始化一些App数据很有必要。
如果说后续配置了App的启动图,再到我们页面的启动页会显示两张,解决方法也很简单,就是将App的启动图和我们页面的启动页图设置成同一张图即可
4、 编写LaunchPage.js
- import React, {useEffect} from 'react';
- import {NativeModules, Platform, StatusBar, View} from 'react-native';
- import {useNavigation} from '@react-navigation/native';
- import {commonSize, commonStyle} from 'src/assets/css/commonStyle';
- import {storageSync} from 'src/utils/storage';
- import {navigateReplace, setNavigation} from 'src/utils/navigation';
- import {useSafeAreaInsets} from 'react-native-safe-area-context';
- import {CtImage} from 'src/components';
- import Orientation from '@hortau/react-native-orientation-locker';
-
- const LaunchPage = () => {
- // 给 navigation.js 传递 navigation
- const navigation = useNavigation();
- setNavigation(navigation);
- const insets = useSafeAreaInsets();
-
- // 获取状态栏高度
- const {StatusBarManager} = NativeModules;
- if (Platform.OS === 'ios') {
- commonSize.statusBarHeight = StatusBarManager.HEIGHT;
- } else if (Platform.OS === 'android') {
- commonSize.statusBarHeight =
- (StatusBarManager && StatusBarManager.HEIGHT) || StatusBar.currentHeight;
- }
-
- // 获取iOS安全区域距离
- // 注意 iOS的状态栏高度 与 iOS的顶部安全距离 不一定一样高
- // 在布局特殊全面屏头部的时候 建议使用 iOS的顶部安全距离
- if (Platform.OS === 'ios') {
- commonSize.safeAreaInsetTop = insets.top;
- commonSize.safeAreaInsetBottom = insets.bottom;
- commonSize.safeAreaInsetLeft = insets.left;
- commonSize.safeAreaInsetRight = insets.right;
- }
-
- // 获取当前设备的方向
- commonSize.screenOrientation = Orientation.getInitialOrientation();
-
- useEffect(() => {
- // 判断用户是否是第一层启动App 是则进入引导页 否则进入首页
- setTimeout(async () => {
- let isFirstLaunchApp = await storageSync.getStorage('isFirstLaunchApp');
- if (Number(isFirstLaunchApp) === 1) {
- goHome();
- } else {
- goGuide();
- }
- }, 1000);
- }, []);
-
- const goHome = () => {
- navigateReplace('TabBarNavigator');
- };
-
- return (
- <View style={commonStyle.container}>
- <CtImage source={require('src/assets/images/img_launchPage.jpg')} />
- </View>
- );
- };
-
- export default LaunchPage;
5、编写GuidePage.js
- import React, {useState} from 'react';
- import {StyleSheet, View} from 'react-native';
- import {CustomSwiper, CtBtn} from 'src/components';
- import {commonStyle} from 'src/assets/css/commonStyle';
- import {navigateReplace} from 'src/utils/navigation';
- import {storageSync} from 'src/utils/storage';
-
- const GuidePage = () => {
- const [swiperCurrentIndex, setSwiperCurrentIndex] = useState(0);
- const guideList = [
- {
- image_url: require('src/assets/images/img_GuidePage01.jpg'),
- name: '001',
- },
- {
- image_url: require('src/assets/images/img_GuidePage02.jpg'),
- name: '002',
- },
- {
- image_url: require('src/assets/images/img_GuidePage03.jpg'),
- name: '003',
- },
- ];
- const getSwiperChange = item => {
- setSwiperCurrentIndex(item.index);
- };
- const guideSwiperMask = () => {
- if (swiperCurrentIndex === guideList.length - 1) {
- return (
- <View style={[commonStyle.flexCenter, styles.swiperMaks]}>
- <CtBtn
- btnText={"Let's go"}
- onPress={() => {
- storageSync.setStorage('isFirstLaunchApp', 1);
- navigateReplace('TabBarNavigator');
- }}
- />
- </View>
- );
- } else {
- return <View style={styles.swiperMaks} />;
- }
- };
-
- return (
- <View style={styles.container}>
- <CustomSwiper
- onSwiperChange={getSwiperChange}
- data={guideList}
- autoplay={false}
- />
- {guideSwiperMask(guideList)}
- </View>
- );
- };
-
- export default GuidePage;
-
- const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- swiperMaks: {
- position: 'absolute',
- left: 0,
- right: 0,
- bottom: 60,
- },
- });
这个页面就是一个轮播图,轮播到最后一张引导图的时候,显示一个按钮,点击按钮,进入首页
6、编写TabBarNavigator.js
- import React from 'react';
- import {StyleSheet, Image} from 'react-native';
- import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
- import {commonColors} from 'src/assets/css/commonStyle';
- import Home from './Home';
- import My from './My';
-
- const Tab = createBottomTabNavigator();
-
- const TabBarNavigator = () => {
- return (
- <Tab.Navigator
- initialRouteName={Home}
- screenOptions={{
- tabBarHideOnKeyboard: true,
- tabBarInactiveTintColor: commonColors.textColorSecondary,
- tabBarActiveTintColor: commonColors.textColorPrimary,
- tabBarStyle: styles.tabBarStyle,
- }}>
- <Tab.Screen
- name={'Home'}
- component={Home}
- options={{
- headerShown: false,
- tabBarIcon: ({focused}) => (
- <Image
- style={styles.tabBarIcon}
- source={
- focused
- ? require('src/assets/images/tabBar/tab_home_active.png')
- : require('src/assets/images/tabBar/tab_home.png')
- }
- />
- ),
- }}
- />
- <Tab.Screen
- name={'My'}
- component={My}
- options={{
- headerShown: false,
- tabBarIcon: ({focused}) => (
- <Image
- style={styles.tabBarIcon}
- source={
- focused
- ? require('src/assets/images/tabBar/tab_my_active.png')
- : require('src/assets/images/tabBar/tab_my.png')
- }
- />
- ),
- }}
- />
- </Tab.Navigator>
- );
- };
-
- export default TabBarNavigator;
-
- const styles = StyleSheet.create({
- tabBarStyle: {
- backgroundColor: commonColors.bgColorWhite,
- },
- tabBarIcon: {
- resizeMode: 'cover',
- width: 28,
- height: 28,
- },
- });
7、上面的代码里面,我重新封装了navigation。在 src/utils 下 新建navigation.js
- import React from 'react';
- import {StackActions} from '@react-navigation/native';
- import indexConfig from 'src/config/index.config';
-
- let _navigation;
-
- function setNavigation(navigation) {
- _navigation = navigation;
- }
-
- const navigatePush = (routeName, params) => {
- _navigation.dispatch(StackActions.push(routeName, params));
- };
-
- const navigateReplace = (routeName, params) => {
- _navigation.dispatch(StackActions.replace(routeName, params));
- };
- const navigateBack = (count = 1) => {
- _navigation.dispatch(StackActions.pop(count));
- };
- const navigateToTop = () => {
- _navigation.dispatch(StackActions.popToTop());
- };
-
- const authNavigatePush = (routeName, params) => {
- let accessToken = indexConfig.accessToken;
- if (accessToken) {
- navigatePush(routeName, params);
- } else {
- navigatePush('Login', params);
- }
- };
-
- const authNavigateReplace = (routeName, params) => {
- let accessToken = indexConfig.accessToken;
- if (accessToken) {
- navigateReplace(routeName, params);
- } else {
- navigatePush('Login', params);
- }
- };
-
- export {
- setNavigation,
- navigatePush,
- navigateReplace,
- navigateBack,
- navigateToTop,
- authNavigatePush,
- authNavigateReplace,
- };
在 LaunchPage 页面 调用 setNavigation(navigation); 把 useNavigation hock方法传进来,
这样以来,就不用在每个页面去写 useNavigation。并且 新增了 authNavigatePush 等方法,可以简单判断用户是否登录。
8、此外,贴上我的 src/assets/css/commonStyle.js
- import {Dimensions, Platform, StatusBar, StyleSheet} from 'react-native';
-
- const {width, height} = Dimensions.get('window');
-
- const commonColors = {
- colorPrimary: '#FFD200',
- colorPrimaryRgba: 'rgba(255, 210, 0, 0.2)',
-
- colorSuccess: '#07c160',
- colorWarning: '#F59A23',
- colorDanger: '#ee0a24',
- colorInfo: '#fffbe8',
-
- bgColorBlack: '#000',
- bgColorWhite: '#fff',
- bgColorPrimary: '#F5F5F5',
- bgColorTransparent: 'transparent',
-
- textColorPrimary: '#333',
- textColorRegular: '#666',
- textColorSecondary: '#999',
- textColorPlaceholder: '#E0E0E0',
-
- borderColorBase: '#AAA',
- borderColorDark: '#999',
- borderColorLight: '#E5E5E5',
- borderColorLighter: '#E0E0E0',
- };
-
- const commonSize = {
- screenOrientation: '',
- width: width,
- height: height,
- statusBarHeight: 0,
- safeAreaInsetTop: 0,
- safeAreaInsetBottom: 0,
- safeAreaInsetLeft: 0,
- safeAreaInsetRight: 0,
- navBarHeight: 44,
-
- radiusMedium: 12,
- radiusSmall: 8,
- radiusMini: 4,
-
- borderWidth: StyleSheet.hairlineWidth,
- };
- const commonStyle = {
- /** flex **/
- flexLeftCenter: {
- flexDirection: 'row',
- alignItems: 'center',
- },
- flexCenter: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'center',
- },
- flexRightCenter: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'flex-end',
- },
- flexBetween: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- },
- flexColumnLeft: {
- flexDirection: 'column',
- alignItems: 'flex-start',
- },
- flexColumnCenter: {
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'center',
- },
- flexColumnRight: {
- flexDirection: 'column',
- alignItems: 'flex-end',
- },
- flexColumnBetween: {
- flexDirection: 'column',
- justifyContent: 'space-between',
- },
- flexAround: {
- flexDirection: 'row',
- justifyContent: 'space-around',
- },
- flexWrap: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- },
-
- testBorder: {
- borderWidth: 5,
- borderColor: 'red',
- },
- bgFFF: {
- backgroundColor: commonColors.bgColorWhite,
- },
- bg000: {
- backgroundColor: commonColors.bgColorBlack,
- },
- container: {
- flex: 1,
- position: 'relative',
- backgroundColor: commonColors.bgColorPrimary,
- },
- relative: {
- position: 'relative',
- },
- absolute: {
- position: 'absolute',
- },
- };
-
- export {commonColors, commonSize, commonStyle};
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。