RN-Navigation 的使用

作者: 精神病患者link常 | 来源:发表于2017-08-22 18:00 被阅读268次

    本文内容
    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',
        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 = {
            title:'第一个页面自定义标题',
            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效果一样

    相关文章

      网友评论

        本文标题:RN-Navigation 的使用

        本文链接:https://www.haomeiwen.com/subject/dxoarxtx.html