React Native 0.43之前 ‘react-native’包里面,但0.43之后了’rea移除了rect-native’。网上的大部分资料,也是ReactNative 0.43之前的 Navigator的用法,然而我用的0.44版本在开发,这就….
参考: http://facebook.github.io/react-native/docs/navigation.html
安装 ‘react-navigator’依赖
于是我按着文档 https://reactnavigation.org/docs/intro/ 来安装:
在项目目录下执行命令安装:
-- -
结果呵呵哒:
E:\hybrid\react_native_pro\Project02>npm installnpm WARN peerDependencies The peer dependency react@* included from react-navigation will nonpm WARN peerDependencies longer be automatically installed to fulfill the peerDependencynpm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.npm WARN peerDependencies The peer dependency react@* included from react-native-drawer-layout-polyfill will nonpm WARN peerDependencies longer be automatically installed to fulfill the peerDependencynpm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.npm WARN peerDependencies The peer dependency react@* included from react-native-tab-view will nonpm WARN peerDependencies longer be automatically installed to fulfill the peerDependencynpm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.npm ERR! install trying to install 15.5.4 to E:\hybrid\react_native_pro\Project02\node_modules\react-navigation\node_modules\reactnpm ERR! install but already installed versions [ '15.5.4' ]npm ERR! Windows_NT 10.0.14393npm ERR! argv "D:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "install"npm ERR! node v4.4.7npm ERR! npm v2.15.12npm ERR! code EPEERINVALIDnpm ERR! peerinvalid The package react@16.0.0-alpha.6 does not satisfy its siblings' peerDependencies requirements!npm ERR! peerinvalid Peer react-native@0.44.0 wants react@16.0.0-alpha.6npm ERR! peerinvalid Peer react-navigation@1.0.0-beta.11 wants react@*npm ERR! peerinvalid Peer react-test-renderer@16.0.0-alpha.6 wants react@^16.0.0-alpha.6npm ERR! Please include the following file with any support request:npm ERR! E:\hybrid\react_native_pro\Project02\npm-debug.log```
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
最后我的解决办法是 安装npm3:
npm install -g npm@3
然后重新执行上面的命令安装。
开始学习
HelloWorld
首先根据官方文档的实例代码编写出来看看效果:
'user react'import React, {Component} from 'react';import {AppRegistry, View, Button, Text} from 'react-native';import {StackNavigator} from 'react-navigation'class HomeScreen extends Component { static navigationOptions = { title: 'Welcome' } render() { const {navigate} = this.props.navigation; return ( <View> <Text> Hello,Navigator</Text> <Button title="Chat With Lucy" //跳转第二个页面,第二个参数,向第二个页面传入参数{user:'Lucy'} onPress={() => navigate('Chat', {user: 'Lucy'})} > </Button> </View> ); }}/** * 第二个页面 */class ChatScreen extends Component { /*可以定义一个函数来读取上个页面传过来的参数*/ static navigationOptions = (({navigation}) => ({ title: `Chat with ${navigation.state.params.user}` })) render() { const { params } = this.props.navigation.state; return ( <View> <Text> Hello , {params.user}</Text> </View> ); }}const Project02 = StackNavigator({ Home: {screen: HomeScreen}, Chat: {screen: ChatScreen},});AppRegistry.registerComponent('Project02', () => Project02);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
该代码实现了:
1.定义了2个页面 HomeScreen和ChartScreen。在HomeScreen中有个按钮,点击跳转到到第二个页面并传参。
Navigators
介绍
Navigators是用来定义为你应用顶用导航架构用的,你也可以通过配置让它为您渲染公共的元素,比如头部或者TabBar。
用来构建Navigator的函数
- StackNavigator —— 用来提供类似“栈”的那张导航,比如启动一个页面,这个新的页面覆盖在旧的页面上,继续按返回键这个新的页面将“弹出”又出现旧的页面。
- TabNavigator —— 提供一个TabBar让用户在几个页面之前切换,这种类似:以Android为例,效果等于TabLayout+ViewPager+Fragment那种。
- DrawerNavigator ——提供一个抽屉,左滑出现。
使用Navigators
使用Navigators我们主要学习2个属性,下文Screen指的是我们的页面组件(即上文,HelloWorld中的HomeScreen,和ChildScreen等)
* Screen navigation prop ,我们可以使用它来调用导航操作,比如启动另一个页面。
* Screen navigationOptions, 我们可以用来定义navigator的显示属性,比如(title,tab label等)
在顶层组件使用导航
上面一个条目,我们讲到用 screen 的 navigation prop可以进行导航操作,但如果我们要在外部操作导航怎么办呢?
我们可以这样:声明一个Navigators的引用,我们可以使用这个引用进行操作,例如:
const AppNavigator = StackNavigator(SomeAppRouteConfigs);class App extends React.Component { someEvent() { this.navigator && this.navigator.dispatch({ type: 'Navigate', routeName, params }); } render() { return ( <AppNavigator ref={nav => { this.navigator = nav; }} /> ); }}
注意,这种解决方案应该只用在最顶层的navigator。
Navigation 容器
当navigation prop没有设置的时候,这个Navigation会自动显示在顶层,她将是一个透明的容器。
当渲染navigaor的时候,这个navigation props 是可选的,如果不设置,它也会有一些默认的操作,比如可以处理URL,外部链接、Android会返回键等。这是因为这些系统自带的navigator(StackNavigator、TabNavigator)他们内部使用了createNavigationContainer
方法,通常,这个方法被用来设置 navigator prop 去支持一些函数。
顶部Navigators接受以下属性:
onNavigationStateChange(prevState, newState, action)
这个用来获得Navigation的状态,它可以接收前一个状态,和最新的状态,以及操作
uriPrefix
用来设置url的前缀,表示那些url可以被我们的app处理。
下面,我贴一个例子,来演示以下 uriPrefix
和onNavigationStateChange(prevState, newState, action)
的用法
import React from 'react';import { AppRegistry, Text, View, Button,} from 'react-native';import {TabNavigator, StackNavigator} from 'react-navigation';class RecentChatsScreen extends React.Component { render() { return <Text>List of recent chats</Text> }}class AllContactsScreen extends React.Component { render() { return ( <View> <Text>Hello, Chat App!</Text> <Button onPress={() => this.props.navigation.navigate('Chat', {user: 'Lucy'})} title="Chat with Lucy" /> </View> ); }}class ChatScreen extends React.Component { static navigationOptions = ({navigation}) => { const {state, setParams} = navigation; const isInfo = state.params.mode === 'info'; const {user} = state.params; return { title: isInfo ? `${user}'s Contact Info` : `Chat with ${user}`, headerRight: (<Button title={isInfo ? 'Done' : `${user}'s Info`} onPress={() => setParams({mode: isInfo ? 'none' : 'info'})} />) }; }; render() { const {params} = this.props.navigation.state; return ( <View> <Text>Chat with {params.user}</Text> </View> ); }}const MainScreenNavigator = TabNavigator({ Recent: { screen: RecentChatsScreen }, All: { screen: AllContactsScreen, },});// MainScreenNavigator.navigationOptions = {title: "Main"};const SimpleApp = StackNavigator({ // 使用 header:null 去掉StackNavigator的导航栏头部 Home: {screen: MainScreenNavigator, navigationOptions: ({navigation}) => ({header: null}),}, Chat: { screen: ChatScreen, //路径,user为可以接受的参数 path: 'chat1/:user', }})const MainApp = () => <SimpleApp //设置 URL's Schema,和 Host uriPrefix={'chat://chat/'} onNavigationStateChange={(preState, newState, action) => { console.log('preState:' + JSON.stringify(preState) + ',newState:' + JSON.stringify(newState) + ',action:' + JSON.stringify(action)); }}/>AppRegistry.registerComponent('Project05', () => MainApp);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
上述代码设置了 uriPrefix
为 ‘chat://chat/,并设置了 ChatScreen中的 path为:
chat1/:user, 其中
:user`表示接受参数 user
那么我们可以使用外部的URL来启动这个页面,
我们以android为例,还需要在AndroidMainifest.xml中的Activity添加一下Intent-Filter。
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT"></category> <data android:scheme="chat" android:host="chat"></data></intent-filter>
安装成功之后,我们在命令行输入:adb shell am start -W -a android.intent.action.VIEW -d "chat://chat/chat1/blueberry"
就可跳转到ChatScreen那个页面了,并传入了参数为blueberry
。
相关的iOS也可以用外部URL访问本应用的页面,可以参考:https://reactnavigation.org/docs/guides/linking
StackNavigator
StackNavigator用来解决屏幕跳转,用它的效果页面导航效果|类似于栈,新启动的页面覆盖在原先的页面上。
使用
import React, {Component} from 'react';import {StyleSheet, View, Button, Text, AppRegistry} from 'react-native';import {StackNavigator} from 'react-navigation';class MainScreen extends Component { static navigationOptions = { title: 'Home', } render() { return ( <View style={{justifyContent: 'center', alignItems: 'center'}}> <Text>{this.props.navigation.state.params.content || ''}</Text> <Button title="Go to Profile" onPress={() => this.props.navigation.navigate('Profile', { title: 'blueberryTitle', content: 'blueberryContent' })}/> </View> ); }}class Profile extends Component { static navigationOptions = ({navigation}) => ( { title: navigation.state.params.title, }) render() { return ( <View> <Text>{this.props.navigation.state.params.content}</Text> </View> ); }}const App = StackNavigator( /** * 路由配置 */ { Home: {screen: MainScreen}, Profile: {screen: Profile, navigationOptions: {headerRight: null}}, }, /** * StackNavigator配置,也可以省略。 */ { // 配置初始化路由名称 initialRouteName: 'Home', // 配置初始化路由的参数 initialRouteParams: {content: '初始化传入的参数'}, // 配置默认的 navigationOptions navigationOptions: {headerRight: <Text>右边Header</Text>}, // 转场动画开始的回到 onTransitionStart: () => { console.log('start') }, });AppRegistry.registerComponent('Project05', () => App);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
API 定义
StackNavigator(RouteConfigs, StackNavigatorConfig)
这个函数接受2个参数,RouteConfigs和StackNavigatorConfig,其中StatckNavigatorConfig
可以省略,如果省略,则默认选择RouteConfigs
中定义的第一个路由。
RoutConfigs
这个路由配置类,是一个Map结构,key是路由的明城,value 是路由的配置。
StackNavigator( { Profile: { screen: ProfileScreen, path: 'people/:name', navigationOptions: ({navigation}) => ({ title: `${navigation.state.params.name}'s Profile'`, }), }, ...MyOtherRoutes, });
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
StackNavigatorConfig
属性 | 作用 | initialRouteName设置初始化路由名称initialRouteParams设置初始化路由的参数navigationOptions设置默认的 navigationOptions (这个参数下文将要介绍)pathsmap结构,覆盖在路由配置中的pathmode定义渲染的和跳转动画的风格,可以设置为card,modal。默认为card。modal可以使界面跳转的而动画是从底部逐渐显示到整个屏幕,这个只对ios有效,因为android,默认转场动画就是从底部逐渐显示到真个屏幕headerMode指定如何渲染头部,可以设置为float,screen,none。如果设置为none,则不会有头部;如果设置为float, 页面跳转时,header是一直在顶部,而且如果header变化了的话,会有动画,有点像android的共享动画;设置成screen的话,头部是跟随这新的页面重新出现。cardStyle可以给页面设置styletransitionConfig一个函数类型,可以用来配置转厂动画onTransitionStart函数类型,动画开始后的回调onTransitionEnd函数类型,动画结束时的回调Screen Navigation Options
属性 | 作用 | titlestring类型,如果设置了它,如果headerTitle或tabBarBabel没有设置的话,将默认会使用这个值headerReact Eelement或 是一个参数是HeaderProps返回Rect Element类型的函数类型。它用来显示为header,设置null的话,可以隐藏headerheaderTitlestring 或者 React Element类型,用来设置header,默认显示的 titleheaderBackTitlestring 类型,用来设置在ios上显示黑色按钮,设置null不显示,默认是titleheaderTruncatedBackTitlestring 类型, 用来设置黑色按钮,当headerBackTitle
没有充满屏幕的时候。headerRightReact Element类型,用来在Header右边添加控件headerLeftReact Element类型,用来在Header左边添加控件headerStyle设置header的样式headerTitleStyle用来设置title组件的样式headerBackTitleStyle用来设置黑色Title的样式headerTintColor用来设置header的颜色headerPressColorAndroid用来设置涟漪效果的颜色,android>5.0有效gesturesEnabled开启的话,你可以用手势 关闭页面,ios默认是true,Android默认是false。我用android机开启该选项,不知道用手势什么关~~。这TM就尴尬了~Navigator Props
我们创建StackNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用
* screenProps 给StackNavigator传入该属性,这个属性将继续传递StackNavigator中的screens,例如:
const SomeStack = StackNavigator({ });<SomeStack screenProps={/* 这个属性将传递给屏幕组件,在屏幕组件使用 this.props.screenProps就可以访问 */}/>
注意这个键一定要是 screenProps,别的可不行哟。
TabNavigator
用这个可以实现几个屏幕之间相互切换,(类似于android原生,TabLayout+Fragment 页面切换那种效果)。
使用
import React, {Component} from 'react';import {StyleSheet, AppRegistry, View, Button, Image,} from 'react-native';import {TabNavigator, TabBarBottom, TabView, TabBarTop} from 'react-navigation';class HomeScreen extends Component { static navigationOptions = { tabBarLabel: 'Home', tabBarIcon: ({tintColor}) => (<Image source={require('./img/chat_online_talk.png')} style={[styles.icon, {tintColor: tintColor}]} />), }; render() { return ( <Button title="Go to Notification" onPress={() => this.props.navigation.navigate('Notifications')}/> ); }}class NotificationScreen extends Component { static navigationOptions = { tabBarLabel: 'Notifications', tabBarIcon: ({tintColor}) => (<Image source={require('./img/notification.png')} style={[styles.icon, {tintColor: tintColor}]} />), // 也可以是其他React Element, // tabBarIcon: ({tintColor}) => (<Button title="按钮" onPress={() => { // }}/>), } ; render() { return ( <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/> ); }}var styles = StyleSheet.create({ icon: {width: 26, height: 26}});const App = TabNavigator( { Home: {screen: HomeScreen}, Notifications: {screen: NotificationScreen} }, { tabBarOptions: { //激活的tab tint颜色 activeTintColor: '#e91e63', //没有激活的tab tint颜色 inactiveTintColor: 'black', //大写转换 upperCaseLabel: true, //显示icon showIcon: true, }, // android默认是TabBarTop,ios默认是TabBarBottom, tabBarComponent: TabBarBottom, // 可以为 top,bottom,用来决定TabBar放置的位置 tabBarPosition: 'bottom', //设置是否可以滑动 swipeEnabled: true, //切换时是否欧动画效果 animationEnabled: false, // 是否懒渲染tabs lazy: false, //第一个被加载的路由名称 initialRouteName: 'Home', //路由名称数组 order: ['Home', 'Notifications'], paths: {Home: 'home', Notifications: 'Notifications'}, backBehavior: true, });AppRegistry.registerComponent('Project05', () => App);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
Api 定义
TabNavigator(RouteConfigs,TabNavigatorConfigs)
RouteConfigs
这个和StackNavigator的RouteConfigs一样,上文已经讲过,用来设置路由信息。
TabNavigatorConfig
属性 | 作用 | tabBarComponent用来设置tab bar的组件,ios默认是TabBarBottom,android默认是TabBarToptabBarPosition用来设置tabBar的位置,可以为 ‘top’ 或者’bottom’swipeEnable用来设置是否可以滑动切换animateEnable用来设置是否有动画效果lazy用来设置是否“懒渲染”tabbartabBarOption用来设置tabBar的一些属性,颜色、样式等等,下文将要介绍initialRouteName初始化路由的名称order路由名称数组paths提供一个map,可以路由对应的pathbackBehavior如果设置为true,那么上面的例子,在第二个页面,按返回将不能反会到前一个页面,也就是是this.props.navigation.goBack()’不会起作用TabBarBottom 的 tabBarOptions 设置
属性 | 作用 | activeTintColor激活的tab的tint 颜色,tint颜色值,icon和Label的颜色activeBackgroundColor激活tab的背景颜色inactiveTintColor没被激活的tint颜色inactiveBackgroundColor没被激活的tab的背景色showLabel是否显示label,默认是truestyletab bar的样式labelStylelabel的样式tabStyletab的样式TabBarTop 的 tabBarOptions设置
属性 | 作用 | activeTintColor激活的tab的tint 颜色,tint颜色值,icon和Label的颜色inactiveTintColor没被激活的tint颜色showIcon是否显示icon,默认是falseshowLabel是否显示label,默认是trueupperCaseLabel是够开启大写转换,默认是truepressColor按压颜色,涟漪效果,andorid>5.0有效pressOpacity按压颜色,透明度变换,android<5.0 和ios可用。scrollEnabledtabs是够可以滑动tabStyletab的样式indicatorStyle底部指示器的样式labelStylelabel的样式iconStyleicon的样式styletab bar的样式举个栗子:
tabBarOptions: { labelStyle: { fontSize: 12, }, tabStyle: { width: 100, }, style: { backgroundColor: 'blue', },}
Screen Navigation Options
属性 | 作用 | title标题,如果headerTitle,和tabBarLabel,不设置的话,就默认是titletabBarVisible决定隐藏还是显示tab bartabBarIcon可以是一个React Eclement,或者是一个参数为{focused:boolean,tintColor:string}
返回Rect Element的函数,用来显示在Tab Bar上tabBarLabelstring类型,或者React Element类型,或者是参数为{focused:boolean,tintColor:string}
返回React Element的函数Navigator Props
我们创建TabNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用
* screenProps 给TabNavigator传入该属性,这个属性将继续传递TabNavigator中的screens。这个和StackNavigator的用法一样,可以参考上文。
DrawerNavigator
这个导航是个抽屉效果,就是类似于QQ那种左滑菜单
使用
import React, {Component} from 'react';import {AppRegistry, StyleSheet, View, Button, Image, ScrollView} from 'react-native';import {DrawerNavigator, DrawerItems} from 'react-navigation';class HomeScreen extends Component { static navigationOptions = { drawerLabel: 'Home', drawerIcon: ({tintColor}) => (<Image style={[styles.icon, {tintColor: tintColor}]} source={require('./img/chat_online_talk.png')}/>), } render() { return ( <View> <Button title="Go to notifications" onPress={() => this.props.navigation.navigate('Notifications')}/> <Button title="打开抽屉" onPress={() => this.props.navigation.navigate('DrawerOpen')}/> <Button title="关闭抽屉" onPress={() => this.props.navigation.navigate('DrawerClose')}/> </View> ); }}class NotificationScreen extends Component { static navigationOptions = { drawerLabel: 'notifications', drawerIcon: ({tintColor}) => (<Image style={[styles.icon, {tintColor: tintColor}]} source={require('./img/notification.png')}/>), } render() { return ( <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/> ); }}const App = DrawerNavigator( {Home: {screen: HomeScreen}, Notifications: {screen: NotificationScreen}}, //一下是DrawerNavigator 的配置 { // 设置宽度 drawerWidth: 300, // 设置从右边拉出,还是左边拉出 drawerPosition: 'left', //默认的的值是 DrawerItems,我们也可以自己配置组件 contentComponent: props => <ScrollView style={{borderWidth: 1, borderColor: 'red'}}><DrawerItems {...props}/></ScrollView>, contentOptions: { items: ['Home', 'Notification'], activeItemKey: 'key', activeTintColor: '#ff863f', activeBackgroundColor: '#d0caff', inactiveTintColor: '#000000', inactiveBackgroundColor: '#fffcf8', //这个设置了没起作用,android,api 0.45 onItemPress: (route) => { console.log('TAG' + JSON.stringify(route)) }, style: null, labelStyle: null, }, // initialRouteName:'Notifications', } );var styles = StyleSheet.create({ icon: {width: 26, height: 26}});AppRegistry.registerComponent('Project05', () => App);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
可以使用一下操作,打开或关闭抽屉
this.props.navigation.navigate('DrawerOpen'); this.props.navigation.navigate('DrawerClose');
Api定义
DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
RouteConfigs
这个和StackNavigator一样,可以参考上文。
DrawerNavigatorConfig
属性 | 作用 | drawerWidth抽屉的宽度drawerPosition枚举值可以为‘left’或’rigt’表示抽屉是在左边还是右边contentComponent可以自定义显示drawer item的组件,默认是实现是DrawerItemcontentOptionsdrawer 内容的一些设置,背景颜色,tint颜色等等,下文将会讲到DrawerItems 的contentOptions
属性 | 作用 | items路由的数组activeItemKey正在活动的路由的keyactiveTintColor正在活动的 item tint 颜色activeBackgroundColor正在活动的item的 背景颜色inactiveTintColor不在活动的item的 tint颜色inactiveBackgroundColor不在活动的item 的背景颜色onItemPress(route)设置一个函数,item被按下时,这个函数将被调用styleDawer的样式labelStylelabel的样式Screen Navigation Options
属性 | 作用 | title标题,如果headerTitle,和tabBarLabel,不设置的话,就默认是titletabBarVisible决定隐藏还是显示tab bartabBarIcon可以是一个React Eclement,或者是一个参数为{focused:boolean,tintColor:string}
返回Rect Element的函数,用来显示在Tab Bar上tabBarLabelstring类型,或者React Element类型,或者是参数为{focused:boolean,tintColor:string}
返回React Element的函数Navigator Props
这个跟StackNavigator 和 TabNavigator的方式一样,可以参考上文。
Screen中的 Navigation 属性
每个Screen都会接收这样一个属性,它其中包含了以下对象:
- navigate 用来跳转到其它页面。
- state 屏幕当前的 state/routes 里面包含有路由信息和参数信息。
- setParams 可以用来改变参数信息。
- goBack 用来关闭当前的活动页面,并返回。
dispatch 给路由发送一个action。
下面来逐个讲解喽~
navigate
它的函数形式为:
navigate(routeName, params, action)
- routeName 要跳转的页面路由名称。
- params 参数信息。
- action 高级用法~,逐个子 action运行在child路由,如果要跳转的页面也是一个Navigator的话。
state
页面可以通过 this.props.navigation.state
获得,它的形式为:
{ routeName: 'profile', key: 'main0', params: { hello: 'world' }}
setParams
改变路由的参数
例如:
class ProfileScreen extends React.Component { render() { const {setParams} = this.props.navigation; return ( <Button onPress={() => setParams({name: 'Lucy'})} title="Set title name to 'Lucy'" /> ) }}
goBack
关闭当前页面,并返回
示例:
class HomeScreen extends React.Component { render() { const {goBack} = this.props.navigation; return ( <View> <Button onPress={() => goBack()} title="Go back from this HomeScreen" /> <Button onPress={() => goBack(null)} title="Go back anywhere" /> <Button onPress={() => goBack('screen-123')} title="Go back from screen-123" /> </View> ) }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
dispatch
给路由发送一个action。用个栗子(没有什么比看代码来的简单明了了)。
import React, {Component} from 'react';import {AppRegistry, View, Button, Image, Text} from 'react-native';import {NavigationActions, TabNavigator} from 'react-navigation';class MainScreen extends Component { render() { return ( <View> <Button title="跳转到Child页面" onPress={() => this.props.navigation.navigate('Child')}/> <Text>{this.props.navigation.state.params ? this.props.navigation.state.params.title : ''}</Text> </View> ); }}class ChildScreen extends Component { render() { const navigationActions = NavigationActions.navigate({ routeName: 'Home', params: {title: 'blueberryTitle'} }); return ( <View> <Button title="返回" onPress={() => this.props.navigation.goBack()}/> <Button title="返回Home显示title" onPress={() => this.props.navigation.dispatch(navigationActions)}/> </View> ); }}const App = TabNavigator( {Home: {screen: MainScreen,}, Child: {screen: ChildScreen}});AppRegistry.registerComponent('NavigationUsage', () => App);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
上面核心代码:
const navigationActions = NavigationActions.navigate({ routeName: 'Home', params: {title: 'blueberryTitle'} });
this.props.navigation.dispatch(navigationActions)
NavigationActions创建了一个acionts,然后使用dispatch去执行了,上面的执行效果就是,挑战到了Home页面,并传入了参数{title:'blueberryTitle'}
。
Naviation Actions
上文已经简单延时了navigation.dispatch()
的用法。
它支持的action有:
- navigate 跳转到其他路由
- Rest 使用一个新的State替换当前的state。
- Back 返回到前一个状态
- Set Params 给你个路由设置 参数。
- Init 如果state没有定义,使用它初始化第一个状态。
Navigate
用法:
import { NavigationActions } from 'react-navigation'const navigateAction = NavigationActions.navigate({ routeName: 'Profile', params: {}, action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})})this.props.navigation.dispatch(navigateAction)
属性 | 作用 | routeName路由名称params参数action高级用法,如果他要跳转的路由也是一个Navigator,用可以用来设置那个Navigator的actionReset
用来重新设置路由记录
const resetAction = NavigationActions.reset({ index: 1, actions: [ NavigationActions.navigate({ routeName: 'Profile'}), NavigationActions.navigate({ routeName: 'Settings'}) ]})this.props.navigation.dispatch(resetAction
注意 index的值 必须在0 - actions.lenght的范围内,不能越界,指定当前在栈中的位置。
Back
使用方法:
const backAction = NavigationActions.back({ key: 'Profile'})this.props.navigation.dispatch(backAction)
key为路由的唯一身份,但是我设置了以后,使用this.props.navigation.dispatch()
没有效果,不设置的话,可以返回,我使用的Andorid机测试。
SetParams
const setParamsAction = NavigationActions.setParams({ params: { title: 'Hello' }, key: 'screen-123',})this.props.navigation.dispatch(setParamsAction)
Screen Navigation Options
配置navigatinOptions
可以用2中方法来设置 navigationOptions
静态配置
示例:
class MyScreen extends React.Component { static navigationOptions = { title: 'Great', };...
动态配置
示例:
class ProfileScreen extends React.Component { static navigationOptions = ({ navigation, screenProps }) => ({ title: navigation.state.params.name + "'s Profile!", headerRight: <Button color={screenProps.tintColor} {...} />, });
这个函数接收的参数为props,props参数中包含 navigation,screenProps ,navigationOptions。返回值用来决定设置的navigationOpiotns。
参数的结构如下:
+ Props
- navigation
- screenProps
- navigationOptions
一般的Navigation Options 配置方法
class MyScreen extends React.Component { static navigationOptions = { title: 'Great', };...
其他的配置方法
可以在配置路由的时候设置:
const SimpleApp = StackNavigator({ Home: {screen: MainScreenNavigator, navigationOptions: ({navigation}) => ({header: null}),}, Chat: { screen: ChatScreen, path: 'chat1/:user', }},{})
还可以在Navigation 配置中设置
const App = StackNavigator( { Home: {screen: MainScreen}, Profile: {screen: Profile, navigationOptions: {headerRight: null}}, }, { navigationOptions: {headerRight: <Text>右边Header</Text>}, });
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
示例代码地址
https://github.com/blueberryCoder/RNDemo/tree/master/NavigationUsage
参考
https://reactnavigation.org/docs/intro/headers