RN-Navigation 的使用

本文内容
1、navigation、tabbar 的分离、navigation的使用
2、传值、回调
3、每个页面设置 navigator
4、navigation reset方法
5、关于返回指定页面(原)
5、关于返回指定页面(新)

程序目录

3D6B6EE2-5488-4648-811B-A2A7F5E06322.png

一、navigation、tabbar 的分离、navigation的使用

index.ios.js

require('./AppRoot/root');

root.js

/**
 * Created by mymac on 2017/8/18.
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';
import {StackNavigator} from "react-navigation";

import Navigator from './natigation';

/*
 navigation 构造函数
 */
const Navigation = StackNavigator(Navigator.AppNavigationRouterConfigs, Navigator.AppNavigationStackConfigs);


class MainComponent extends Component {

    render() {
        return (
            <Navigation 
                    onNavigationStateChange={(prevNav, nav, action)=>{
                            // 每次导航改变时,都会走这个方法,可以再次判断逻辑
                            console.log('prevNav=',prevNav);
                            console.log('nav=',nav);
                            console.log('action=',action);
            />
        );
    }

}

AppRegistry.registerComponent('Navigation', () => MainComponent);

navigation.js

/**
 * Created by mymac on 2017/8/18.
 */
import {TabNavigator} from "react-navigation";

import FirstCtrl from '../controllers/firstCtrl';
import SecondCtrl from '../controllers/secondCtrl';
import ThirdCtrl from '../controllers/thirdCtrl';

import AppTab from './tabBar';

// 动画效果
// forHorizontal:从右向左进入
// forVertical:从下向上进入
// forFadeFromBottomAndroid:从底部淡出
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';


/*
 title - 可以作为头部标题 headerTitle ,或者Tab标题 tabBarLabel
 header - 自定义的头部组件,使用该属性后系统的头部组件会消失
 headerTitle - 头部的标题,即页面的标题
 headerBackTitle - 返回标题,默认为 title
 headerTruncatedBackTitle - 返回标题不能显示时(比如返回标题太长了)显示此标题,默认为 “Back”
 headerRight - 头部右边组件
 headerLeft - 头部左边组件
 headerStyle - 头部组件的样式
 headerTitleStyle - 头部标题的样式
 headerBackTitleStyle - 头部返回标题的样式
 headerTintColor - 头部颜色
 headerPressColorAndroid - Android 5.0 以上MD风格的波纹颜色
 gesturesEnabled - 否能侧滑返回, iOS 默认 true , Android 默认 false
 */

/*
 构造函数
 */
const Tab = TabNavigator(AppTab.AppRootTabBarRouteConfigs, AppTab.AppRootTabBarNavigatorConfigs);

/* 配置路由,所有要跳转的页面都需要在此声明 */

const AppNavigationRouterConfigs = {
    TabBar: {
        screen: Tab,
        navigationOptions: ({navigation}) => ({
            title: '首页',
            headerBackTitle: '首页', // 给下一个页面的返回按钮设置标题 , 类似iOS的 backBarItem
        }),
    },

    First: {
        screen: FirstCtrl,
        navigationOptions: ({navigation}) => ({
            title: '第一页',
            headerBackTitle: '第一页', // 给下一个页面的返回按钮设置标题

        }),
    },
    Second: {
        screen: SecondCtrl,
        navigationOptions: ({navigation}) => ({
            title: '第二页',
            headerBackTitle: '第二页', // 给下一个页面的返回按钮设置标题

        }),
    },
    Third: {
        screen: ThirdCtrl,
        navigationOptions: ({navigation}) => ({
            title: '第三页',
            headerBackTitle: '第三页', // 给下一个页面的返回按钮设置标题

        }),
    }

};

/*
 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 - 页面跳转动画一旦完成会马上调用
 */

const AppNavigationStackConfigs = {
    initialRouteName: 'TabBar',
    initialRouteParams: {initParams: '初始化时传递参数'},
    navigationOptions: {
        title: '路由页面的配置选项,它会被 RouteConfigs 参数中的 navigationOptions 的对应属性覆盖',
    },
    mode: 'card',
    headerMode: 'screen',
    transitionConfig: ()=>({
        screenInterpolator: CardStackStyleInterpolator.forHorizontal,
    }),
    onTransitionStart: (() => {
        console.log('页面跳转动画开始');
    }),
    onTransitionEnd: (() => {
        console.log('页面跳转动画结束');
    }),
};

export default {
    AppNavigationRouterConfigs,
    AppNavigationStackConfigs
};

tabBar.js

/**
 * Created by mymac on 2017/8/18.
 */

import React, { Component } from 'react';

import {TabBarBottom} from "react-navigation";

import Home from '../subTabBars/select';
import Follow from '../subTabBars/follow';
import Explor from '../subTabBars/explor';
import Mine from '../subTabBars/mine';

/*自定义的 tabBar 图片 view*/
import TabBarItem from './tabBarItem';
/*
    创建下面的四个 tabar
*/
const AppRootTabBarRouteConfigs = {
    Home:{
        screen: Home,
        navigationOptions: {
            tabBarLabel: '首页',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    focused={focused}
                    normalImage={require('../images/select.png')}
                    selectedImage={require('../images/select_select.png')}
                />
            ),
        }
    },
    Follow:{
        screen: Follow,
        navigationOptions: {
            tabBarLabel: '关注',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    focused={focused}
                    normalImage={require('../images/follow_follow.png')}
                    selectedImage={require('../images/follow_follow_select.png')}
                />
            ),
           tabBarOnPress:(obj)=>{
                console.log(obj);
                obj.jumpToIndex(obj.scene.index)
            },
        }
    },
    Explor:{
        screen: Explor,
        navigationOptions: {
            tabBarLabel: '发现',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    focused={focused}
                    normalImage={require('../images/explor_explor.png')}
                    selectedImage={require('../images/explor_explor_select.png')}
                />
            ),
        }
    },
    Mine:{
        screen: Mine,
        navigationOptions: {
            tabBarLabel: '我的',
            tabBarIcon: ({focused, tintColor}) => (
                <TabBarItem
                    focused={focused}
                    normalImage={require('../images/mine_mine.png')}
                    selectedImage={require('../images/mine_mine_select.png')}
                />
            ),
        }
    },
};

/*
 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的样式
 */

/*
 TabBarTop:
    indicatorStyle: {height: 0}, // android 中TabBar下面会显示一条线,高度设为 0 后就不显示线了, 不知道还有没有其它方法隐藏???
    showIcon: true, // android 默认不显示 icon, 需要设置为 true 才会显示
 */

const AppRootTabBarNavigatorConfigs = {
    initialRouteName: 'Home',
    defaultNavigationOptions: {
         headerStyle: {
             backgroundColor: '#f4511e',
         },
         headerTintColor: '#fff',
         headerTitleStyle: {
             fontWeight: 'bold',
         },
    },
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    lazy: true,
    tabBarOptions: {
        activeTintColor: 'red',
        inactiveTintColor: 'black',
        showLabel: true,
        style:{ // 在此处可以设置tabbar的属性,height、marginBottom等。iPhone X适配时,需要在此处进行适配处理
            backgroundColor: 'yellow',
        },
        labelStyle: {  // 在此处可以设置tabbar的title的属性,大小、颜色等
            fontWeight: 'bold',
            fontSize: 12,
        },
        iconStyle: {
            // 在此处可以设置tabbar的icon的属性
        }
    }
};

export default {
    AppRootTabBarRouteConfigs,
    AppRootTabBarNavigatorConfigs
};


/* 在此直接导出 Tab ,在 navigation 里面是得不到的,只有在 navigation 里面 调用构造方法*/
/*
 构造函数
 export default Tab = TabNavigator(AppTab.AppRootTabBarRouteConfigs, AppTab.AppRootTabBarNavigatorConfigs);
 */

二、传值、回调

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
} from 'react-native';

export default class select extends Component {
    render() {
        const {navigate,} = this.props.navigation;
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    精选
                </Text>

                <TouchableOpacity style={{marginTop: 20}} onPress={()=>{

                    // 传递参数,及 回调函数
                    navigate('First', {params: '你好第一页', callBack:(value)=>{
                        console.log(value);
                    }});
                }}>
                    <Text style={styles.welcome}>
                        点击跳转到第一个页面
                    </Text>
                </TouchableOpacity>

            </View>

        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    }
});



/**
 * Created by mymac on 2017/8/18.
 */
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    TouchableOpacity
} from 'react-native';

export default class firstCtrl extends Component {

 
    render() {
        const {navigate} = this.props.navigation;
        // 收到的参数
        const {params} = this.props.navigation.state;

        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    上一个页面给当前页传值为:{params.params}
                </Text>
                <TouchableOpacity style={{marginTop: 20}} onPress={()=>{

                    navigate('Second', {params: '你好第二页'});

                }}>
                    <Text style={styles.welcome}>
                        点击跳转到第二个页面
                    </Text>
                </TouchableOpacity>

                <TouchableOpacity style={{marginTop: 100}} onPress={()=>{
                    //回调函数
                    params.callBack('123456789');

                    this.props.navigation.goBack();

                }}>
                    <Text style={styles.welcome}>
                        点击返回首页,并传值:"hello world"
                    </Text>
                </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    }
});


三、每个页面设置 navigator

 * Created by mymac on 2017/8/18.
 */
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    TouchableOpacity
} from 'react-native';

export default class firstCtrl extends Component {

    /*
     title - 可以作为头部标题 headerTitle ,或者Tab标题 tabBarLabel
     header - 自定义的头部组件,使用该属性后系统的头部组件会消失
     headerTitle - 头部的标题,即页面的标题
     headerBackTitle - 返回标题,默认为 title
     headerTruncatedBackTitle - 返回标题不能显示时(比如返回标题太长了)显示此标题,默认为 “Back”
     headerRight - 头部右边组件
     headerLeft - 头部左边组件
     headerStyle - 头部组件的样式
     headerTitleStyle - 头部标题的样式
     headerBackTitleStyle - 头部返回标题的样式
     headerTintColor - 头部标题颜色
     headerPressColorAndroid - Android 5.0 以上MD风格的波纹颜色
     gesturesEnabled - 否能侧滑返回, iOS 默认 true , Android 默认 false
     */
/*
    static navigationOptions = ({ navigation, navigationOptions, screenProps }) => {
        return {
          title: navigation.getParam('otherParam', 'A Nested Details Screen'),
          headerRight: (
              <Text>right</Text>
          ),
          headerTitle: <customTitle/> 自定义标题组件。
        };
    };
*/
    static navigationOptions = {
        title:'第一个页面自定义标题', // 或者 headerTitle:'第一个页面自定义标题'
        headerRight: (
            <Text>right</Text>
        ),
        //headerLeft: null, 没有返回按钮
        headerTintColor: 'red',
        header:null, // 隐藏 导航条
    };

    render() {
     
        return (
            <View style={styles.container}>
              
            </View>
        );
    }
}


四、navigation reset方法

import { NavigationActions } from 'react-navigation'

重新注册导航栈,将原来的清空
const resetAction = NavigationActions.reset({
  index: 0, // 默认选中第一个元素
  actions: [
    NavigationActions.navigate({ routeName: 'Profile'}) // Profile将这个js放入导航栈中
  ]
})
this.props.navigation.dispatch(resetAction)


import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 1, // 默认选中第二个 元素,  如果此处写为 2  这越界了,因为下面栈里只有两个元素
  actions: [
    NavigationActions.navigate({ routeName: 'Profile'}), //  Profile将这个js放入导航栈中,第一个元素
    NavigationActions.navigate({ routeName: 'Settings'}) // Settings将这个js放入导航栈中,第二个元素
  ]
})
this.props.navigation.dispatch(resetAction)


5、关于返回指定页面(原)

原思路:每一个页面进行navigate的时候都有一个key,所以在使用goBack(key)的时候,只要知道要返回页面的key就可以了。方法就是把页面的key存起来,存在redux中

<Navigation onNavigationStateChange={(prevNav, nav, action)=>{
                            // 每次导航改变时,都会走这个方法,可以再次判断逻辑,比如切换tabar需要调用方法
                            console.log('prevNav=',prevNav);
                            console.log('nav=',nav);
                            console.log('action=',action);

                            let route = {};
                            nav.routes.map((item)=>{
                                route[item.routeName] = item.key
                            });

                            console.log('route:',route);

                            this.props.saveRouteNameAndId(route);

                }}/>

5、关于返回指定页面(新),请更新react-navigation到最新

再也不用去存key啦~

this.props.navigation 提供的几种方法:

    goBack
    navigate
    pop
    popToTop
    getParam
    push
    replace

this.props.navigation.pop(2) // 2就是要返回几个页面

this.props.navigation.popToTop() // 直接返回到主导航

this.props.navigation.push('HomeDetail1') // push 和 navigate效果一样

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容