React-navigation之进阶2_repint

来源:互联网 发布:史密斯热水器 贵 知乎 编辑:程序博客网 时间:2024/06/13 21:13

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/ 来安装:

在项目目录下执行命令安装:

npm install --save react-navigator
  • 1
  • 1

结果呵呵哒:

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
  • 1
  • 1

然后重新执行上面的命令安装。

开始学习

HelloWorld

首先根据官方文档的实例代码编写出来看看效果:

/** * Sample React Native App * https://github.com/facebook/react-native * @flow */'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是用来定义为你应用顶用导航架构用的,你也可以通过配置让它为您渲染公共的元素,比如头部或者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() {        // call navigate for AppNavigator here:        this.navigator && this.navigator.dispatch({ type: 'Navigate', routeName, params });    }    render() {        return (            <AppNavigator ref={nav => { this.navigator = nav; }} />        );    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意,这种解决方案应该只用在最顶层的navigator。

当navigation prop没有设置的时候,这个Navigation会自动显示在顶层,她将是一个透明的容器。 
当渲染navigaor的时候,这个navigation props 是可选的,如果不设置,它也会有一些默认的操作,比如可以处理URL,外部链接、Android会返回键等。这是因为这些系统自带的navigator(StackNavigator、TabNavigator)他们内部使用了createNavigationContainer方法,通常,这个方法被用来设置 navigator prop 去支持一些函数。

顶部Navigators接受以下属性: 
onNavigationStateChange(prevState, newState, action) 
这个用来获得Navigation的状态,它可以接收前一个状态,和最新的状态,以及操作

uriPrefix 
用来设置url的前缀,表示那些url可以被我们的app处理。

下面,我贴一个例子,来演示以下 uriPrefixonNavigationStateChange(prevState, newState, action)的用法

/** * Created by Administrator on 5/27/2017. */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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

安装成功之后,我们在命令行输入: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用来解决屏幕跳转,用它的效果页面导航效果|类似于栈,新启动的页面覆盖在原先的页面上。

使用
/** * Created by blueberry on 6/15/2017. */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为路由的名称,对应的值则是路由的配置        Profile: {            // `ProfileScreen` 是一个 React UI组件的定义,它就是这个路由的界面            screen: ProfileScreen,// 当 `ProfileScreen` 被StackNavigator加载之后,他将会有一个`navigation` 属性。            // 这个是一个可选项,如果想让这个界面可以被外部链接启动,可以设置这个,:name是用来传入参数的,这个上文讲过。            path: 'people/:name',            // 设置这个可以覆盖我们在React Component中设置的navigationOptions属性            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就尴尬了~

我们创建StackNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用 
* screenProps 给StackNavigator传入该属性,这个属性将继续传递StackNavigator中的screens,例如:

const SomeStack = StackNavigator({    // config});<SomeStack    screenProps={/* 这个属性将传递给屏幕组件,在屏幕组件使用 this.props.screenProps就可以访问 */}/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意这个键一定要是 screenProps,别的可不行哟。

TabNavigator

用这个可以实现几个屏幕之间相互切换,(类似于android原生,TabLayout+Fragment 页面切换那种效果)。

使用
/** * Created by blueberry on 6/15/2017. */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',    },}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
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的函数

我们创建TabNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用 
* screenProps 给TabNavigator传入该属性,这个属性将继续传递TabNavigator中的screens。这个和StackNavigator的用法一样,可以参考上文。

DrawerNavigator

这个导航是个抽屉效果,就是类似于QQ那种左滑菜单

使用
/** * Created by blueberry on 6/15/2017. */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'); // open drawerthis.props.navigation.navigate('DrawerClose'); // close drawer
  • 1
  • 2
  • 1
  • 2
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的函数

这个跟StackNavigator 和 TabNavigator的方式一样,可以参考上文。

Screen中的 Navigation 属性

每个Screen都会接收这样一个属性,它其中包含了以下对象:

  • navigate 用来跳转到其它页面。
  • state 屏幕当前的 state/routes 里面包含有路由信息和参数信息。
  • setParams 可以用来改变参数信息。
  • goBack 用来关闭当前的活动页面,并返回。
  • dispatch 给路由发送一个action。

    下面来逐个讲解喽~

它的函数形式为: 
navigate(routeName, params, action) 
- routeName 要跳转的页面路由名称。 
- params 参数信息。 
- action 高级用法~,逐个子 action运行在child路由,如果要跳转的页面也是一个Navigator的话。

state

页面可以通过 this.props.navigation.state获得,它的形式为:

{    // 路由的名称    routeName: 'profile',        //唯一的id        key: 'main0',    // 参数    params: { hello: 'world' }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
setParams

改变路由的参数

例如:

class ProfileScreen extends React.Component {    render() {        const {setParams} = this.props.navigation;        return (            <Button                onPress={() => setParams({name: 'Lucy'})}                title="Set title name to 'Lucy'"            />        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
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。用个栗子(没有什么比看代码来的简单明了了)。

/** * Created by blueberry on 6/15/2017. */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'}        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
 this.props.navigation.dispatch(navigationActions)
  • 1
  • 1

NavigationActions创建了一个acionts,然后使用dispatch去执行了,上面的执行效果就是,挑战到了Home页面,并传入了参数{title:'blueberryTitle'}

上文已经简单延时了navigation.dispatch()的用法。 
它支持的action有:

  • navigate 跳转到其他路由
  • Rest 使用一个新的State替换当前的state。
  • Back 返回到前一个状态
  • Set Params 给你个路由设置 参数。
  • Init 如果state没有定义,使用它初始化第一个状态。

用法:

import { NavigationActions } from 'react-navigation'const navigateAction = NavigationActions.navigate({    routeName: 'Profile',    params: {},    action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})})this.props.navigation.dispatch(navigateAction)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
属性作用routeName路由名称params参数action高级用法,如果他要跳转的路由也是一个Navigator,用可以用来设置那个Navigator的action
Reset

用来重新设置路由记录

const resetAction = NavigationActions.reset({    index: 1,    actions: [        NavigationActions.navigate({ routeName: 'Profile'}),        NavigationActions.navigate({ routeName: 'Settings'})    ]})this.props.navigation.dispatch(resetAction
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意 index的值 必须在0 - actions.lenght的范围内,不能越界,指定当前在栈中的位置。

Back

使用方法:

const backAction = NavigationActions.back({    key: 'Profile'})this.props.navigation.dispatch(backAction)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

key为路由的唯一身份,但是我设置了以后,使用this.props.navigation.dispatch()没有效果,不设置的话,可以返回,我使用的Andorid机测试。

SetParams
const setParamsAction = NavigationActions.setParams({    params: { title: 'Hello' },    key: 'screen-123',})this.props.navigation.dispatch(setParamsAction)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • parmas 为参数
  • key 为要修改的路由的身份

Screen Navigation Options

配置navigatinOptions

可以用2中方法来设置 navigationOptions

静态配置

示例:

class MyScreen extends React.Component {    static navigationOptions = {        title: 'Great',    };...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
动态配置

示例:

class ProfileScreen extends React.Component {    static navigationOptions = ({ navigation, screenProps }) => ({        title: navigation.state.params.name + "'s Profile!",        headerRight: <Button color={screenProps.tintColor} {...} />,    });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

这个函数接收的参数为props,props参数中包含 navigation,screenProps ,navigationOptions。返回值用来决定设置的navigationOpiotns。

参数的结构如下: 
+ Props 
- navigation  
- screenProps 
- navigationOptions

一般的Navigation Options 配置方法
class MyScreen extends React.Component {    static navigationOptions = {        title: 'Great',    };...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
其他的配置方法
可以在配置路由的时候设置:
const SimpleApp = StackNavigator({    // 使用 header:null 去掉StackNavigator的导航栏头部    Home: {screen: MainScreenNavigator, navigationOptions: ({navigation}) => ({header: null}),},    Chat: {        screen: ChatScreen,        //路径,user为可以接受的参数        path: 'chat1/:user',    }},{})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
还可以在Navigation 配置中设置
const App = StackNavigator(    /**     * 路由配置     */    {        Home: {screen: MainScreen},        Profile: {screen: Profile, navigationOptions: {headerRight: null}},    },    /**     * StackNavigator配置,也可以省略。     */    {        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

阅读全文
0 0