此处将为大家介绍关于ReactNative之ReactNavigation导航器的详细内容,并且为您解答有关react-native导航栏的相关问题,此外,我们还将为您介绍关于@react-navig
此处将为大家介绍关于React Native之React Navigation导航器的详细内容,并且为您解答有关react-native导航栏的相关问题,此外,我们还将为您介绍关于@ react-navigation / native和@ react-navigation / stack读取整个堆栈、React Native Paper Provider 和 React Navigation NavigationContainer 在 React Native Web 中导致错误、React Native react-navigation 导航使用详解、react native 导航路由组件react-navigation的使用的有用信息。
本文目录一览:- React Native之React Navigation导航器(react-native导航栏)
- @ react-navigation / native和@ react-navigation / stack读取整个堆栈
- React Native Paper Provider 和 React Navigation NavigationContainer 在 React Native Web 中导致错误
- React Native react-navigation 导航使用详解
- react native 导航路由组件react-navigation的使用
React Native之React Navigation导航器(react-native导航栏)
最近在学习React Native,关于界面跳转这一块,文档上面写的并不清晰,自己也是研究了很久才搞清楚用法,这里记录下。@H_301_1@
译注:从0.44版本开始,Navigator被从react native的核心组件库中剥离到了一个名为react-native-deprecated-custom-components的单独模块中。如果你需要继续使用Navigator,则需要先npm i facebookarchive/react-native-custom-components安装,然后从这个模块中import,即import { Navigator } from ‘react-native-deprecated-custom-components’.@H_301_1@
今后社区主推的导航控件是react-navigation。@H_301_1@
如果我们安装了yarn,那么只要使用yarn add react-navigation命令安装这个库就可以使用了。@H_301_1@
如果我们在index.js入口中这么写的话@H_301_1@
import { AppRegistry } from 'react-native'; import App from './App'; AppRegistry.registerComponent('ReactNativeSimple',() => App);
那么我们想在App组件中跳转到别的页面,那么我们就可以把navigation申明在App文件中然后导出,这里需要注意,default关键字不能申明在App类中了要申明在navigation导出的时候。
ps:navigation必须default申明原因我猜测因为default导出的类,在适用import导入的时候可以随便改写名字例如上面如果App是用default申明导出的那么上面代码import App from ‘./App’;我们可以随便写成import xxx from ‘./App’; 都可以,如果不适用default申明的话那么import 导入时候必须跟类名一模一样。 我们导出的navigation变量名叫啥系统也不知道,所以只能用default申明了。@H_301_1@
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React,{ Component } from "react"; import { Platform,StyleSheet,Text,View,FlatList,Image,TouchableOpacity,TouchableHighlight,NativeModules,Alert } from "react-native"; import DemoComponent from "./DemoComponent"; const instructions = Platform.select({ ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",android: "Double tap R on your keyboard to reload,\n" + "Shake or press menu button for dev menu" }); import { StackNavigator } from "react-navigation"; export class App extends Component<Props> { static defaultProps = { textValue: "首页默认文本" }; constructor(props) { super(props); this.state = { textValue: this.props.textValue }; } testOnpress = () => { this.props.navigation.navigate("Profile",{ name: "Jane" }); }; render() { return ( <View style={styles.container}> <FlatList data={[{ key: "wubo" }]} renderItem={({ item }) => ( <View style={styles.listItem}> <Image style={{ width: 30,height: 30 }} source={require("./icon.jpg")} /> <Text onPress={this.testOnpress}>{this.state.textValue}</Text> </View> )} /> </View> ); } } const Navigate= StackNavigator({ App: { screen: App },Profile: { screen: DemoComponent } }); const styles = StyleSheet.create({ container: { flex: 1,backgroundColor: "#F5FCFF" },listItem: { flexDirection: "row",justifyContent: "center" },welcome: { fontSize: 20,textAlign: "center",margin: 10 },instructions: { textAlign: "center",color: "#333333",marginBottom: 5 } }); export default AppN1;
我们在Navigation路由中申明了组件页面后,这个组件就具有了navigation props属性,我们就可以跳转到路由中申明的其他页面了。@H_301_1@
但如果我们这样写的话主要有几点问题。 1. 我们的App没有用default申明,所以其他地方导出使用时必须是App类名不能更改这点上面已经提到。 2 . 如果我们把每个界面要跳转的页面都申明在这个组件类中,那么缺乏统一的管理显得非常混乱,这是不允许的。
所以上面方法虽然可以实现跳转但是强烈不建议这么做。@H_301_1@
常规方式我们可以单独创建个js类单独管理所有要跳转的页面。
例如我创建个NavigationManager.js文件@H_301_1@
import { StackNavigator } from "react-navigation"; import DemoComponent from "./DemoComponent"; import App from "./App"; const Navigate = StackNavigator( { App: { screen: App,navigationoptions: { header: null } },Profile: { screen: DemoComponent } },{ initialRouteName: "App" } ); export default Navigate;
这里默认显示的页面是App组件
我们可以把所有需要跳转的页面都放在这个js申明的navigation中,然后默认导出,记住navigation一定要默认导出。@H_301_1@
然后App组件代码我们修改成这样@H_301_1@
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React,Alert } from "react-native"; const instructions = Platform.select({ ios: "Press Cmd+R to reload,\n" + "Shake or press menu button for dev menu" }); export default class App extends Component<Props> { static defaultProps = { textValue: "首页默认文本" }; constructor(props) { super(props); this.state = { textValue: this.props.textValue }; } testOnpress = () => { this.props.navigation.navigate("Profile",height: 30 }} source={require("./icon.jpg")} /> <Text onPress={this.testOnpress}>{this.state.textValue}</Text> </View> )} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1,marginBottom: 5 } });
我们在index.js中把入口从App改成Navigate.@H_301_1@
import { AppRegistry } from 'react-native'; import Navigate from './NavigationManager'; AppRegistry.registerComponent('ReactNativeSimple',() => Navigate);
此时跟我们之前是一样的效果,但是把所有要跳转的页面管理在一起,代码就清爽很多,后期利于维护。@H_301_1@
@ react-navigation / native和@ react-navigation / stack读取整个堆栈
您可以使用如下所示的useNavigationState钩子来获取当前状态
https://reactnavigation.org/docs/use-navigation-state/
import {useNavigationState} from '@react-navigation/native';
const state = useNavigationState((state) => state);
alert(JSON.stringify(state.routes));
这将在路线中显示屏幕
React Native Paper Provider 和 React Navigation NavigationContainer 在 React Native Web 中导致错误
如何解决React Native Paper Provider 和 React Navigation NavigationContainer 在 React Native Web 中导致错误?
我是 React-native 和 React-native-web 的初学者。我目前正在处理一个使用 React-Native-paper
和 @react-navigation/native
库的现有项目。我正在尝试使用现有代码/项目作为 Web 应用程序运行。但是当我在 App.js 中使用以下代码时,我在运行 Web 应用程序的控制台中收到一个错误:
import React from ''react'';
import {Provider} from ''react-native-paper'';
import {NavigationContainer} from ''@react-navigation/native'';
export const App = props => {
return (
<NavigationContainer>
<Provider>
<Navigator />
</Provider>
</NavigationContainer>
);
};
我得到的错误是:
Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
at AppContainer (webpack://web_tester/./node_modules/react-native-web/dist/exports/AppRegistry/AppContainer.js?:22:24)
react-dom.development.js:14906 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This Could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
at Object.throwInvalidHookError (VM231 react-dom.development.js:14906)
at Object.useContext (VM227 react.development.js:1504)
at eval (VM252 index.js:83)
at renderWithHooks (VM231 react-dom.development.js:14985)
at updateForwardRef (VM231 react-dom.development.js:17044)
at beginWork (VM231 react-dom.development.js:19098)
at HTMLUnkNownElement.callCallback (VM231 react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (VM231 react-dom.development.js:3994)
at invokeGuardedCallback (VM231 react-dom.development.js:4056)
at beginWork$1 (VM231 react-dom.development.js:23959)
我创建了一个包含错误的简单 git repository。请看一下。
任何其他方面的见解都会有所帮助。并提前致谢。
解决方法
尝试将 react-native-paper 提供程序放在外面。我的应用使用以下代码使用 react-native 和 react-native-web 工作正常。
我已经通过 Expo which is the recommended way 设置了 react-native-web:引用自 react-native-web 文档:“通常建议您使用 Expo。”
<PaperProvider theme={theme} settings={settings}>
<NavigationContainer>
<RootStackScreens />
</NavigationContainer>
</PaperProvider>
React Native react-navigation 导航使用详解
一、开源库介绍
今年1月份,新开源的react-natvigation库备受瞩目。在短短不到3个月的时间,github上星数已达4000+。Fb推荐使用库,并且在React Native当前最新版本0.44中将Navigator删除。react-navigation据称有原生般的性能体验效果。可能会成为未来React Native导航组件的主流军。本篇内容基于【 ^1.0.0-beta.9 】版本来介绍关于该库的使用和实战技巧。可以看到,虽然是beta版本,不过基本稳定,大家可放心在项目中使用。奉上 react-navigation 官方文档
该库包含三类组件:
(1)StackNavigator:用来跳转页面和传递参数
(2)TabNavigator:类似底部导航栏,用来在同一屏幕下切换不同界面
(3)DrawerNavigator:侧滑菜单导航栏,用于轻松设置带抽屉导航的屏幕
二、react-navigation使用
具体内容大致分为如下:
(1)react-navigation库属性介绍
(2)StackNavigator、TabNavigator实现界面间跳转,Tab切换
(3)StackNavigator界面间跳转、传值、取值
(4)DrawerNavigator实现抽屉导航菜单
(5)DrawerNavigator扩展功能
(6)自定义react-navigation
1、StackNavigator属性介绍
navigationOptions:配置StackNavigator的一些属性。
- title:标题,如果设置了这个导航栏和标签栏的title就会变成一样的,不推荐使用
- header:可以设置一些导航的属性,如果隐藏顶部导航栏只要将这个属性设置为null
- headerTitle:设置导航栏标题,推荐
- headerBackTitle:设置跳转页面左侧返回箭头后面的文字,默认是上一个页面的标题。可以自定义,也可以设置为null
- headerTruncatedBackTitle:设置当上个页面标题不符合返回箭头后的文字时,默认改成"返回"
- headerRight:设置导航条右侧。可以是按钮或者其他视图控件
- headerLeft:设置导航条左侧。可以是按钮或者其他视图控件
- headerStyle:设置导航条的样式。背景色,宽高等
- headerTitleStyle:设置导航栏文字样式
- headerBackTitleStyle:设置导航栏‘返回''文字样式
- headerTintColor:设置导航栏颜色
- headerPressColorAndroid:安卓独有的设置颜色纹理,需要安卓版本大于5.0
- gesturesEnabled:是否支持滑动返回手势,iOS默认支持,安卓默认关闭
screen:对应界面名称,需要填入import之后的页面
mode:定义跳转风格
card:使用iOS和安卓默认的风格
modal:iOS独有的使屏幕从底部画出。类似iOS的present效果
headerMode:返回上级页面时动画效果
float:iOS默认的效果
screen:滑动过程中,整个页面都会返回
none:无动画
cardStyle:自定义设置跳转效果
- transitionConfig: 自定义设置滑动返回的配置
- onTransitionStart:当转换动画即将开始时被调用的功能
- onTransitionEnd:当转换动画完成,将被调用的功能
path:路由中设置的路径的覆盖映射配置
initialRouteName:设置默认的页面组件,必须是上面已注册的页面组件
initialRouteParams:初始路由参数
注:大家可能对于path不太理解。path属性适用于其他app或浏览器使用url打开本app并进入指定页面。path属性用于声明一个界面路径,例如:【/pages/Home】。此时我们可以在手机浏览器中输入:app名称://pages/Home来启动该App,并进入Home界面。
2、TabNavigator属性介绍
screen:和导航的功能是一样的,对应界面名称,可以在其他页面通过这个screen传值和跳转。
navigationOptions:配置TabNavigator的一些属性
title:标题,会同时设置导航条和标签栏的title
tabBarVisible:是否隐藏标签栏。默认不隐藏(true)
tabBarIcon:设置标签栏的图标。需要给每个都设置
tabBarLabel:设置标签栏的title。推荐
导航栏配置
tabBarPosition:设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:''top'',''bottom'')
swipeEnabled:是否允许在标签之间进行滑动
animationEnabled:是否在更改标签时显示动画
lazy:是否根据需要懒惰呈现标签,而不是提前,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐为true
trueinitialRouteName: 设置默认的页面组件
backBehavior:按 back 键是否跳转到第一个Tab(首页), none 为不跳转
tabBarOptions:配置标签栏的一些属性iOS属性
activeTintColor:label和icon的前景色 活跃状态下
activeBackgroundColor:label和icon的背景色 活跃状态下
inactiveTintColor:label和icon的前景色 不活跃状态下
inactiveBackgroundColor:label和icon的背景色 不活跃状态下
showLabel:是否显示label,默认开启 style:tabbar的样式
labelStyle:label的样式安卓属性
activeTintColor:label和icon的前景色 活跃状态下
inactiveTintColor:label和icon的前景色 不活跃状态下
showIcon:是否显示图标,默认关闭
showLabel:是否显示label,默认开启 style:tabbar的样式
labelStyle:label的样式 upperCaseLabel:是否使标签大写,默认为true
pressColor:material涟漪效果的颜色(安卓版本需要大于5.0)
pressOpacity:按压标签的透明度变化(安卓版本需要小于5.0)
scrollEnabled:是否启用可滚动选项卡 tabStyle:tab的样式
indicatorStyle:标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height设置为0来暂时解决这个问题
labelStyle:label的样式
iconStyle:图标样式
3、DrawerNavigator属性介绍
DrawerNavigatorConfig
- drawerWidth - 抽屉的宽度
- drawerPosition - 选项是左或右。 默认为左侧位置
- contentComponent - 用于呈现抽屉内容的组件,例如导航项。 接收抽屉的导航。 默认为DrawerItems
- contentOptions - 配置抽屉内容
initialRouteName - 初始路由的routeName
order - 定义抽屉项目顺序的routeNames数组。
路径 - 提供routeName到路径配置的映射,它覆盖routeConfigs中设置的路径。
backBehavior - 后退按钮是否会切换到初始路由? 如果是,设置为initialRoute,否则为none。 默认为initialRoute行为
DrawerItems的contentOptions属性
- activeTintColor - 活动标签的标签和图标颜色
- activeBackgroundColor - 活动标签的背景颜色
- inactiveTintColor - 非活动标签的标签和图标颜色
- inactiveBackgroundColor - 非活动标签的背景颜色
内容部分的样式样式对象
labelStyle - 当您的标签是字符串时,要覆盖内容部分中的文本样式的样式对象
从上述中大致了解了react-navigation三种组件的一些基本属性,所以到我们甩起袖子撸代码见证下奇迹了。
4、使用StackNavigator + TabNavigator实现Tab界面切换、界面间导航
API定义:StackNavigator(RouteConfigs, StackNavigatorConfig)、TabNavigator(RouteConfigs, TabNavigatorConfig)
(1)集成 react-navigation:在终端执行 【 npm install react-navigation --save 】
(2)界面中导入必要组件:
import {StackNavigator,TabNavigator,TabBarBottom} from ''react-navigation''; import HomeScreen from ''./pages/HomePage''; import MineScreen from ''./pages/MinePage'';
(3)定义TabNavigator:
const Tab = TabNavigator( { Home:{ screen:HomeScreen, navigationOptions:({navigation}) => ({ tabBarLabel:''首页'', tabBarIcon:({focused,tintColor}) => ( <TabBarItem tintColor={tintColor} focused={focused} normalImage={require(''./imgs/nav_fav@2x.png'')} selectedImage={require(''./imgs/nav_fav_actived@3x.png'')} /> ) }), }, Mine:{ screen:MineScreen, navigationOptions:({navigation}) => ({ tabBarLabel:''我'', tabBarIcon:({focused,tintColor}) => ( <TabBarItem tintColor={tintColor} focused={focused} normalImage={require(''./imgs/tab_me_nor@3x.png'')} selectedImage={require(''./imgs/tab_me_selected@2x.png'')} /> ) }), }, }, { tabBarComponent:TabBarBottom, tabBarPosition:''bottom'', swipeEnabled:false, animationEnabled:false, lazy:true, tabBarOptions:{ activeTintColor:''#06c1ae'', inactiveTintColor:''#979797'', style:{backgroundColor:''#ffffff'',}, labelStyle: { fontSize: 20, // 文字大小 }, } } );
TabBarItem为封装的组件:
import React,{Component} from ''react''; import {Image} from ''react-native''; export default class TabBarItem extends Component { render() { return( <Image source={ this.props.focused ? this.props.selectedImage : this.props.normalImage } style={ { tintColor:this.props.tintColor,width:25,height:25 } } /> ) } }
可以看到,我们定义了一个名称为【Tab】的TabNavigator的导航组件。在组件中,分为两层参数:
(1)第一层参数定义了要切换的界面,即【首页】、【我】两个界面组件,通过screen属性指定。并且通过navigationOptions属性设置相关属性参数。
(2)设置导航栏的属性参数。
TabNavigator定义好之后,需要用StackNavigator,顾名思义,StackNavigator就是以栈的方式来存放整个界面的,而
TabNavigator是作为一个界面内不同子界面之间切换。所以还需要我们定义StackNavigator:
const Navigator = StackNavigator( { Tab:{screen:Tab}, Product:{screen:ProductScreen} }, { navigationOptions:{ headerBackTitle:null, headerTintColor:''#333333'', showIcon:true, swipeEnabled:false, animationEnabled:false, }, mode:''card'', });
看起来和TabNavigator很相似,同样是指定了两个参数:
(1)指定要跳转的界面组件。同样是screen属性标识界面组件,不多赘述。
(2)定义跳转属性参数,即顶部导航栏的一些参数设置和跳转方式。
可以看到,我们将Tab作为一个界面设置到了StackNavigator。这样就可以实现Tab导航和界面间跳转的效果了。
最后就是在render中引用StackNavigator:
export default class Demo extends Component { render() { return ( <Navigator /> ); } }
StackNavigator还提供了onNavigationStateChange回调方法,用来监听导航状态的改变。具体不再赘述。实现了界面跳转和切换,那么就该来增加下界面之间的感情了,来看看如何实现界面之间的传值和取值。
5、界面间跳转、传值、取值
在界面组件注入到StackNavigator中时,界面组件就被赋予了navigation属性,即在界面组件中可以通过【this.props.navigation】获取并进行一些操作。
navigation属性中提供了很多的函数简化界面间操作,简单列举几点:
(1)通过navigate函数实现界面之间跳转:
this.props.navigation.navigate(''Mine'');
参数为我们在StackNavigator注册界面组件时的名称。同样也可以从当前页面返回到上一页:
// 返回上一页 this.props.navigation.goBack();
(2)跳转时传值:
this.props.navigation.navigate(''Mine'',{info:''传值过去''});
第一个参数同样为要跳转的界面组件名称,第二个参数为要传递的参数,info可以理解为key,后面即传递的参数。
(3)获取值:
{this.props.navigation.state.params.info}
通过state.params来获取传来的参数,后面为key值。此处为info。
以上实现完成,我们就可以愉快的玩耍啦~~ 什么?忽然发现在Android上的效果和IOS效果不一样。老板要界面一致哇~ 怎么办?那就需要我们进行简单的适配了。
三、DrawerNavigator实现抽屉导航
1、导航实现
API定义:DrawerNavigator(RouteConfigs,DrawerNavigatorConfig)
(1)界面中定义DrawerNavigator:
import {StackNavigator,TabNavigator,DrawerNavigator} from ''react-navigation''; import HomeScreen from ''./pages/HomePage''; import MineScreen from ''./pages/MinePage''; export default class Demo extends Component { render() { return ( <Navigator /> ); } } const Navigator = DrawerNavigator({ Home:{screen:HomeScreen}, Mine:{screen:MineScreen}, }); const styles = StyleSheet.create({ container: { flex: 1, }, }); AppRegistry.registerComponent(''Demo'', () => Demo);
定义方式和StackNavigator基本类似,不再赘述。
(2)HomeScreen界面和MineScreen界面:
export default class HomePage extends Component { static navigationOptions = { drawerLabel: ''首页'', drawerIcon:({tintColor}) => ( <Image source={require(''./../imgs/ic_happy.png'')} style={[styles.icon, {tintColor: tintColor}]}/> ), }; render() { return( <View style={{flex:1}}> <Text onPress={this._skip.bind(this)}>点击跳转</Text> </View> ); } _skip() { this.props.navigation.navigate("Mine"); } } export default class MinePage extends Component { static navigationOptions = { drawerLabel:''我'', drawerIcon: ({ tintColor }) => ( <Image source={require(''./../imgs/ic_h.png'')} style={[styles.icon, {tintColor: tintColor}]} /> ), }; render() { return( <View style={{flex:1}}> <Text onPress={this._skip.bind(this)}>返回上一界面</Text> </View> ); } /** * 跳转 */ _skip() { this.props.navigation.goBack(); } }
代码很简单,实现了界面之间的跳转。
2、扩展功能
(1)默认DrawerView不可滚动。要实现可滚动视图,必须使用contentComponent自定义容器,如下所示:
{ drawerWidth:200, 抽屉位置:“对” contentComponent:props => <ScrollView> <DrawerItems {... props} /> </ ScrollView> }
(2)可以覆盖导航使用的默认组件,使用DrawerItems自定义导航组件:
import {DrawerItems} from ''react-navigation''; const CustomDrawerContentComponent = (props) => ( <View style = {style.container}> <DrawerItems {... props} /> </View> );
(3)嵌套抽屉导航
如果您嵌套DrawerNavigation,抽屉将显示在父导航下方。
四、自定义react-navigation
(1)适配顶部导航栏标题:
测试中发现,在iphone上标题栏的标题为居中状态,而在Android上则是居左对齐。所以需要我们修改源码,进行适配。
【node_modules -- react-navigation -- src -- views -- Header.js】的326行代码处,修改为如下:
title: { bottom: 0, left: TITLE_OFFSET, right: TITLE_OFFSET, top: 0, position: ''absolute'', alignItems: ''center'', }
上面方法通过修改源码的方式其实略有弊端,毕竟扩展性不好。还有另外一种方式就是,在navigationOptions中设置headerTitleStyle的alignSelf为 '' center ''即可解决。
(2)去除返回键文字显示:
【node_modules -- react-navigation -- src -- views -- HeaderBackButton.js】的91行代码处,修改为如下即可。
{Platform.OS === ''ios'' && title && <Text onLayout={this._onTextLayout} style={[styles.title, { color: tintColor }]} numberOfLines={1} > {backButtonTitle} </Text>}
将上述代码删除即可。
(3)动态设置头部按钮事件:
当我们在头部设置左右按钮时,肯定避免不了要设置按钮的单击事件,但是此时会有一个问题,navigationOptions是被修饰为static类型的,所以我们在按钮的onPress的方法中不能直接通过this来调用Component中的方法。如何解决呢?在官方文档中,作者给出利用设置params的思想来动态设置头部标题。那么我们可以利用这种方式,将单击回调函数以参数的方式传递到params,然后在navigationOption中利用navigation来取出设置到onPress即可:
componentDidMount () { /** * 将单击回调函数作为参数传递 */ this.props.navigation.setParams({ switch: () => this.switchView() }); }
/** * 切换视图 */ switchView() { alert(''切换'') }
static navigationOptions = ({navigation,screenProps}) => ({ headerTitle: ''企业服务'', headerTitleStyle: CommonStyles.headerTitleStyle, headerRight: ( <NavigatorItem icon={ Images.ic_navigator } onPress={ ()=> navigation.state.params.switch() }/> ), headerStyle: CommonStyles.headerStyle });
(4)结合BackHandler处理返回和点击返回键两次退出App效果
点击返回键两次退出App效果的需求屡见不鲜。相信很多人在react-navigation下实现该功能都遇到了很多问题,例如,其他界面不能返回。也就是手机本身返回事件在react-navigation之前拦截了。如何结合react-natigation实现呢?和大家分享两种实现方式:
(1)在注册StackNavigator的界面中,注册BackHandler:
componentWillMount(){ BackHandler.addEventListener(''hardwareBackPress'', this._onBackAndroid ); } componentUnWillMount(){ BackHandler.addEventListener(''hardwareBackPress'', this._onBackAndroid); } _onBackAndroid=()=>{ let now = new Date().getTime(); if(now - lastBackPressed < 2500) { return false; } lastBackPressed = now; ToastAndroid.show(''再点击一次退出应用'',ToastAndroid.SHORT); return true; }
(2)监听react-navigation的Router
/** * 处理安卓返回键 */ const defaultStateAction = AppNavigator.router.getStateForAction; AppNavigator.router.getStateForAction = (action,state) => { if(state && action.type === NavigationActions.BACK && state.routes.length === 1) { if (lastBackPressed + 2000 < Date.now()) { ToastAndroid.show(Constant.hint_exit,ToastAndroid.SHORT); lastBackPressed = Date.now(); const routes = [...state.routes]; return { ...state, ...state.routes, index: routes.length - 1, }; } } return defaultStateAction(action,state); };
(5)实现Android中界面跳转左右切换动画
react-navigation在Android中默认的界面切换动画是上下。如何实现左右切换呢?很简单的配置即可:
import CardStackStyleInterpolator from ''react-navigation/src/views/CardStackStyleInterpolator'';
然后在StackNavigator的配置下添加如下代码:
transitionConfig:()=>({ screenInterpolator: CardStackStyleInterpolator.forHorizontal, })
(6)解决快速点击多次跳转
当我们快速点击跳转时,会开启多个重复的界面,如何解决呢。其实在官方git中也有提示,解决这个问题需要修改react-navigation源码:
找到scr文件夹中的addNavigationHelpers.js文件,替换为如下文本即可:
export default function<S: *>(navigation: NavigationProp<S, NavigationAction>) { // 添加点击判断 let debounce = true; return { ...navigation, goBack: (key?: ?string): boolean => navigation.dispatch( NavigationActions.back({ key: key === undefined ? navigation.state.key : key, }), ), navigate: (routeName: string, params?: NavigationParams, action?: NavigationAction,): boolean => { if (debounce) { debounce = false; navigation.dispatch( NavigationActions.navigate({ routeName, params, action, }), ); setTimeout( () => { debounce = true; }, 500, ); return true; } return false; }, /** * For updating current route params. For example the nav bar title and * buttons are based on the route params. * This means `setParams` can be used to update nav bar for example. */ setParams: (params: NavigationParams): boolean => navigation.dispatch( NavigationActions.setParams({ params, key: navigation.state.key, }), ), }; }
五、效果图
抽屉导航:
以上就是我们实战中常用的属性和技巧。具体的操作还需要大家在实践过程中测试体会。希望对大家的学习有所帮助,也希望大家多多支持。
- React Router 5.1.0使用useHistory做页面跳转导航的实现
- 利用React高阶组件实现一个面包屑导航的示例
- Android开发之React Navigation 导航栏样式调整+底部角标消息提示
- React Native中导航组件react-navigation跨tab路由处理详解
- 详解React Native顶|底部导航使用小技巧
- react-native使用react-navigation进行页面跳转导航的示例
- react实现导航栏二级联动
react native 导航路由组件react-navigation的使用
navigation的几个难点和问题:
1.底部tab是否可以加上中间的大按钮? 如果加上,如何触发事件? js文件放哪?
2.navigation的登录注册页面。成功后应该不能返回刚刚的登录页面?清空页面栈?
3.登录成功跳转到大厅?意图页面?还是当前所在页?弹出model是不是可以解决所有问题?登录成功如何重刷当前页?
一、前言
在 React Native
中,官方已经推荐使用 react-navigation
来实现各个界面的跳转和不同板块的切换。 react-navigation
主要包括三个组件:
TabNavigator
切换组件 ,用来实现同一个页面上不同界面的切换,即tab选项卡StackNavigator
导航组件,用于实现各个页面之间的跳转,即页面跳转(通过stack栈记录)DrawerNavigator
抽屉组件,可以实现侧滑的抽屉效果
本次我们主要说说前两个,DrawerNavigator
笔者不曾使用
(一)、怎么使用navigation(入口和概览)
export default class Navigator extends Component {
render() {
return(
<Navigator />
)
}
}
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs)
上面的StackNavigator就是react-navigation
的导航组件:
StackNavigator
导航组件,用于实现各个页面之间的跳转,即页面跳转(通过stack栈记录)
那么它的两个参数 StackNavigator(StackRouteConfigs, StackNavigatorConfigs) 又是干啥的呢?
(二)、怎么使用StackNavigator
const StackRouteConfigs = {
MainTab: {
screen: MainTab,
navigationOptions: ({navigation}) => ({
//主页大厅的tab及其相关页面
}),
},
Datail: {
screen: DatailPage,
navigationOptions: ({navigation}) => ({
}),
},
};
const StackNavigatorConfig = {
initialRouteName: ''MainTab'', //默认先加载的页面
navigationOptions: { //路由页面的配置选项,可定义头部内容、样式
},
mode: ''card'', //页面跳转方式,card 表示原生系统默认的方式和 modal只针对iOS平台,模态跳转
headerMode: ''screen'',页面跳转时,头部的动画模式,有 float 、 screen 、 none 三种
};
StackRouteConfigs参数表示各个页面路由配置,类似于android原生开发中的 AndroidManifest.xml
,它是让导航器知道需要导航的路由对应的页面。
StackNavigatorConfigs参数表示导航器的配置,包括导航器的初始页面、各个页面之间导航的动画、页面的配置选项等等:


initialRouteName - 导航器组件中初始显示页面的路由名称,如果不设置,则默认第一个路由页面为初始显示页面
initialRouteParams - 给初始路由的参数,在初始显示的页面中可以通过 this.props.navigation.state.params 来获取
navigationOptions - 路由页面的配置选项,它会被 RouteConfigs 参数中的 navigationOptions 的对应属性覆盖。
paths - 路由中设置的路径的覆盖映射配置
mode - 页面跳转方式,有 card 和 modal 两种,默认为 card :
card - 原生系统默认的的跳转
modal - 只针对iOS平台,模态跳转
headerMode - 页面跳转时,头部的动画模式,有 float 、 screen 、 none 三种:
float - 渐变,类似iOS的原生效果
screen - 标题与屏幕一起淡入淡出
none - 没有动画
cardStyle - 为各个页面设置统一的样式,比如背景色,字体大小等
transitionConfig - 配置页面跳转的动画,覆盖默认的动画效果
onTransitionStart - 页面跳转动画即将开始时调用
onTransitionEnd - 页面跳转动画一旦完成会马上调用
上面的MainTab表示大厅内的Tab内容
也就是:
TabNavigator
切换组件 ,用来实现同一个页面上不同界面的切换,即tab选项卡
它怎么使用呢???
(三)、怎么使用TabNavigator
const MainTab = TabNavigator(TabRouteConfigs, TabNavigatorConfigs);
const TabNavigatorConfigs = {
initialRouteName: ''Recommend'',
tabBarComponent: TabBarBottom,
tabBarPosition: ''bottom'',
lazy: true,
tabBarOptions: {
activeTintColor: ''red'',
inactiveTintColor: ''#999'',
showIcon: true,
indicatorStyle: {height: 0},
style: {
backgroundColor: ''#fff'',
height: (height*0.08 < 65) ? 65 : height*0.08,
paddingVertical: (height*0.08 < 65) ? 5 : height*0.08/13,
},
labelStyle: {fontSize: 11},
}
};
const TabRouteConfigs = {
Attention: {
screen: AttentionScreen,
navigationOptions: ({navigation}) => ({
tabBarLabel: ''关注'',
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? LocalImage.AttentionSelectedImage : LocalImage.AttentionImage} style={{width: ''33%''}} resizeMode=''contain''> </Image>
),
}),
},
Recommend: {
screen: RecommendScreen,
navigationOptions: ({navigation}) => ({
tabBarLabel: ''推荐'',
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? LocalImage.RecommendSelectedImage : LocalImage.RecommendImage} style={{width: ''33%''}} resizeMode=''contain''> </Image>
),
}),
},
Library: {
screen: LibraryScreen,
navigationOptions: ({navigation}) => ({
tabBarLabel: ''仓库'',
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? LocalImage.LibrarySelectedImage : LocalImage.LibraryImage} style={{width: ''33%''}} resizeMode=''contain''> </Image>
),
}),
},
Profile: {
screen: ProfileScreen,
navigationOptions: ({navigation}) => ({
tabBarLabel: ''我的'',
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? LocalImage.ProfileSelectedImage : LocalImage.ProfileImage} style={{width: ''33%''}} resizeMode=''contain''> </Image>
),
}),
},
};
TabNavigator
切换组件 TabNavigatorConfigs 的配置


tabBarComponent - Tab选项卡组件,有 TabBarBottom 和 TabBarTop 两个值,在iOS中默认为 TabBarBottom ,在Android中默认为 TabBarTop 。
TabBarTop - 在页面的顶部
TabBarBottom - 在页面的底部
tabBarPosition - Tab选项卡的位置,有 top 或 bottom 两个值
swipeEnabled - 是否可以滑动切换Tab选项卡
animationEnabled - 点击Tab选项卡切换界面是否需要动画
lazy - 是否懒加载页面
initialRouteName - 初始显示的Tab对应的页面路由名称
order - 用路由名称数组来表示Tab选项卡的顺序,默认为路由配置顺序
paths - 路径配置
backBehavior - androd点击返回键时的处理,有 initialRoute 和 none 两个值
initailRoute - 返回初始界面
none - 退出
tabBarOptions - Tab配置属性,用在 TabBarTop 和 TabBarBottom 时有些属性不一致:
用于 TabBarTop 时:
activeTintColor - 选中的文字颜色
inactiveTintColor - 未选中的文字颜色
showIcon - 是否显示图标,默认显示
showLabel - 是否显示标签,默认显示
upperCaseLabel - 是否使用大写字母,默认使用
pressColor - android 5.0以上的MD风格波纹颜色
pressOpacity - android 5.0以下或者iOS按下的透明度
scrollEnabled - 是否可以滚动
tabStyle - 单个Tab的样式
indicatorStyle - 指示器的样式
labelStyle - 标签的样式
iconStyle - icon的样式
style - 整个TabBar的样式
用于 TabBarBottom 时:
activeTintColor - 选中Tab的文字颜色
activeBackgroundColor - 选中Tab的背景颜色
inactiveTintColor - 未选中Tab的的文字颜色
inactiveBackgroundColor - 未选中Tab的背景颜色
showLabel - 是否显示标题,默认显示
style - 整个TabBar的样式
labelStyle - 标签的样式
tabStyle - 单个Tab的样式
三、结语
暂时就这样
关于React Native之React Navigation导航器和react-native导航栏的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于@ react-navigation / native和@ react-navigation / stack读取整个堆栈、React Native Paper Provider 和 React Navigation NavigationContainer 在 React Native Web 中导致错误、React Native react-navigation 导航使用详解、react native 导航路由组件react-navigation的使用的相关信息,请在本站寻找。
本文标签: