react-navigation,刷新你的导航

作者: 谦谦君子修罗刀 | 来源:发表于2017-11-05 13:41 被阅读2686次

    在2017年1月,新开源的react-navigation库备受瞩目。它有类似于原生版性能的体验效果,可能会成为未来RN导航组件中的主力军。该库包含三类组件:
    (1)StackNavigator:用来跳转页面和传递参数。stack就是数据结构的堆栈技术,遵循后进先出的原理。
    (2)TabNavigator:类似底部导航栏,用来在同一屏幕下切换不同界面
    (3)DrawerNavigator:侧滑菜单导航栏,用于轻松设置带抽屉导航的屏幕

    来朵花花

    一、属性介绍

    1.1StackNavigator属性

    • navigationOptions:用于配置StackNavigator的一些属性。
      • title:标题,如果设置了该属性,导航栏和标签栏的title就会变成一样。故不建议使用
      • header:设置一些导航的属性,若想要隐藏顶部导航栏则只需要把这个属性设置为null
      • headerTitle:设置导航栏标题
      • headerBackTitle:设置跳转页面左侧返回箭头后面的文字,默认是上一个页面的标题,当然也可以自定义设置设置成null
      • headerTruncatedBackTitle:设置当上个页面标题不符合返回箭头后的文字时,默认改成"返回"
      • headerRight:设置导航条右侧。可以是按钮或者是其他视图控件
      • headerLeft:设置导航条右侧。可以是按钮或者是其他视图控件
      • headerStyle:设置导航条的样式,背景色及宽高等
      • headerTitleStyle:设置导航栏文字样式
      • headerBackTitleStyle:设置导航栏"返回"的文字样式
      • headerTintColor:设置导航栏颜色
      • headerPressColorAndroid:安装独有的设置颜色纹理。当然只有在安卓5.0以上才有效果
      • gesturesEnabled:是否支持滑动返回手势。iOS默认支持,安卓默认关闭
    • screen:对应界面名称,需要填入import之后的页面
    • mode:定义跳转风格
      • card:使用iOS和安卓默认的风格。直接切换
      • modal:iOS独有的使屏幕从底部拖出
    • headerMode:返回上级页面时的动画效果
      • float:iOS的默认效果
      • screen:滑动过程中,整个页面都会返回
      • none:无动画
    • cardStyle:自定义设置跳转效果
      • transitionConfig:自定义设置滑动返回的配置
      • onTransitionStart:当转换动画即将被调用的功能
      • onTransitionEnd:当转换动画完成时被调用的功能
    • path:路由中设置的路径的覆盖映射配置。path用于声明一个界面路径
    • initialRouteName:设置默认的页面组件,必须是已经注册的页面组件
    • initailRouteParams:设置路由参数

    1.2TabNavigator属性

    • screen:和导航的功能一样,对应界面名称,可以在气头页面通过这个screen传值和跳转
    • navigationOptions:配置TabNavigator的一些属性
    • title:标题,会同时设置导航条和标签栏的title
    • tabBarVisible:是否显示标签栏。默认是true不隐藏
    • tabBarIcon:设置标签栏的图标。需要给每一项都设置
    • tabBarLabel:设置标签栏的title

    以下属性配合导航使用

    • tabBarPosition:设置tabBar的位置,属性值为top和bottom。iOS默认在底部,安卓默认在顶部

    • swipeEnabled:是否允许在标签之间进行滑动

    • animationEnabled:是否在更改标签时显示动画

    • lazy:是否在app打开的时候将底部的标签栏全部加载,默认为flase。推荐打开

    • trueInitialRouteName:设置默认的页面组件

    • backBehavior:按back键是否跳转到第一个tab,none为不跳转

    • tabBarOptions:设置标签栏

    • 专属iOS属性

      • activeTintColor:设置在活跃状态下,label和icon的前景色
      • activeBackgroundColor:label和icon的背景色
      • inactiveTintColor:设置在不活跃状态下,label和icon的前景色
      • inactiveTintColor:设置在不活跃状态下,label和icon的背景色
      • showLabel:是否显示label,默认卡其style:tabbar的样式
      • labelStyle:label的样式
    • 安卓属性

      • activeTintColor:label和icon的前景色 活跃状态下
      • inactiveTintColor:label和icon的前景色 不活跃状态下
      • showIcon:是否显示图标,默认关闭
      • showLabel:是否显示label,默认开启 style:tabbar的样式
      • labelStyle:label的样式 upperCaseLabel:是否使标签大写,默认为true
      • pressColor:material涟漪效果的颜色(安卓版本需要大于5.0)
      • pressOpacity:按压标签的透明度变化(安卓版本需要小于5.0)
      • scrollEnabled:是否启用可滚动选项卡 tabStyle:tab的样式
      • indicatorStyle:标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height设置为0来暂时解决这个问题
      • labelStyle:label的样式
      • iconStyle:图标样式

    1.3DrawerNavigator属性介绍

    • DrawerNavigatorConfig属性
      • drawerWidth - 抽屉的宽度
      • drawerPosition - 选项是左或右。 默认为左侧位置
      • contentComponent - 用于呈现抽屉内容的组件,例如导航项。 接收抽屉的导航。 默认为DrawerItems
      • contentOptions - 配置抽屉内容
      • initialRouteName - 初始路由的routeName
      • order - 定义抽屉项目顺序的routeNames数组。
        路径 - 提供routeName到路径配置的映射,它覆盖routeConfigs中设置的路径。
      • backBehavior - 后退按钮是否会切换到初始路由? 如果是,设置为initialRoute,否则为none。 默认为initialRoute行为
      • DrawerItems的contentOptions属性
      • activeTintColor - 活动标签的标签和图标颜色
      • activeBackgroundColor - 活动标签的背景颜色
      • inactiveTintColor - 非活动标签的标签和图标颜色
      • inactiveBackgroundColor - 非活动标签的背景颜色
        内容部分的样式样式对象
      • labelStyle - 当您的标签是字符串时,要覆盖内容部分中的文本样式的样式对象

    二、案例

    2.1StackNavigation案例

    • 集成第三方库
      使用npm安装react-navigation库,--save表示将该组件写入到package.json文件中。
    npm install react-navigation --save
    

    当然,也可以采用yarn工具将该库添加到项目中

     yarn add react-navigation
    
    • 导入组件到项目中

      本项目创建于0.49.2的环境中,这次RN对该版本做了重大改进。安卓端和iOS的文件混合成为index.js文件。而文件App.js注册到了又注册到了index.js文件。故我们将需要用到的代码编写在App.js文件中。

    import {StackNavigator} from 'react-navigation';
    
    • 创建导航,并且添加路由
    import HomeScreen from './HomeScreen'; //导入需要展示的页面
    
    const  Navigator = StackNavigator(
    //设置导航要展示的页面
        {
           HomeScreen:{screen:HomeScreen}   
        },
        //设置navigationOptions属性对象
        {
          navigationOptions: {
            title: '标题', //在导航中显示的标题内容
            headerBackTitle:null,
            headerTintColor:'#333333',
            showIcon:true,
            swipeEnabled:false,
            animationEnabled:false,
          },
          mode:'card',  //设置mode属性
        }
    );
    
    • 在render函数中返回导航
    export default class App extends Component<{}> {
      render() {
        return (
           <Navigator/>
        );
      }
    }
    
    • HomeScreen.js代码实现
    import React, { Component } from 'react';
    import {
        Platform,
        StyleSheet,
        AppRegistry,
        Text,
        View
    } from 'react-native';
    
    export default class HomeScreen extends Component {
        render(){
            return(
                <View style={{flex:1,backgroundColor:'pink'}}>
                    <Text>你好啊 在干嘛呢</Text>
                </View>
            );
        }
    }
    
    效果图

    下面可以来做导航的跳转操作
    为了实现跳转操作的功能,需要先新建一个页面,并且将这个页面添加到导航中去。

    • 导入页面到App.js文件
    import ChatScreen from './ChatScreen'  //新建的文件
    
    const  Navigator = StackNavigator(
        {
           HomeScreen:{screen:HomeScreen},
           ChatScreen:{screen:ChatScreen}  //这是新添加的导航界面
    
    • 跳转操作

    只要界面加入到了导航当中,组件中就会自动添加navigation的navigate属性。使用该属性可以跳转到下一个界面。下面是HomeScreen中的代码。ChatScreen是第二个导航界面。在HomeScreen中添加一个button组件,使用routeName路由名称ChatScreen关联到组件ChatScreen.

    export default class HomeScreen extends Component {
    
        render(){
            return(
                <View style={{flex:1,backgroundColor:'pink'}}>
                    <Text>你好啊 在干嘛呢</Text>
                    <Button
                      onPress={()=>this.props.navigation.navigate('ChatScreen')}
                      title={"chat with lucy"}
                    />
                </View>
            );
        }
    }
    
    • 返回操作

    当第二个界面想要回归到上一个界面时,也要用到navigation的goBack属性。当然导航有自身的返回按钮。以下代码是ChatScreen组件的代码,当用户组件Text也会返回到上一个界面。

    export default class ChatScreen extends Component {
        static navigationOptions = {
            title: 'Chat with Lucy',
        };
        render() {
            return (
                <View>
                    <Text onPress={()=>this.props.navigation.goBack()}>Chat with Lucy</Text>
                </View>
            );
        }
    }
    
    效果图
    • 传递参数
      在ChatScreen页面中,如果直接写死标题则不利于代码的可维护性。所以我们可以在导航的时候传递参数。首先编辑一下HomeScreen组件,传递自定义的属性user参数到路由中去。
    export default class HomeScreen extends Component {
        render(){
            const { navigate } = this.props.navigation;
            return(
                <View style={{flex:1,backgroundColor:'pink'}}>
                    <Text>你好啊 在干嘛呢</Text>
                    <Button
                      onPress={()=>navigate('ChatScreen',{user:'dudu'})}
                      title={"chat with lucy"}
                    />
                </View>
            );
        }
    }
    

    之后可以编辑ChatScreen组件显示的user参数,这个参数通过route来传递。为了代码的健壮性,如果外界的user属性有值,就将user赋值给title。如果没有则让title为空。
    设置导航右边的菜单,设置一个“返回”的文字

    static navigationOptions =({ navigation, screenProps }) => ({
        title: navigation.state.params?navigation.state.params.user:null,
        headerRight:(
            <Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
                返回
            </Text>
        )
    });
    
    • 外界传值

    我们也可以将外界的参数传递给函数内部。下面的代码采用结构赋值的方法,取出导航中状态机的参数params,取出参数中的user,一样可以拿到外界参数。

     render() {
            const {params} = this.props.navigation.state;
            return (
                <View>
                    <Text onPress={()=>this.props.navigation.goBack()}>Chat with {params.user}</Text>
                </View>
            );
        }
    
    效果图

    2.2 TabNavigator案例

    react-navigation组件除了可以用做页面间的跳转,当然也可以用做tab界面之间的切换。

    • 导入react-navigation的子组件。这些组件分别是用于界面切换、跳转、和标签栏外置的摆放。
    import {StackNavigator,TabNavigator,TabBarBottom} from 'react-navigation';
    
    • 封装一个TabBarItem,用于设置每个tab的图片
    import React,{Component} from 'react';
    import {Image} from 'react-native';
    
    export default class TabBarItem extends Component {
    
        render() {
            return(
                <Image source={ this.props.focused ? this.props.selectedImage : this.props.normalImage }
                       style={ { tintColor:this.props.tintColor,width:25,height:25 } }
                />
            )
        }
    
    }
    
    • 导入封装的TabBarItem组件 表示TabBar的每一项
    import TabBarItem from './TabBarItem';
    
    • 定义TabNavigator。定义几个要切换的tab,每个tab设置好对应要显示的屏幕。当然,从之前介绍的属性可知,TabNavigator也拥有navigationOptions属性,它由系统传入navigation参数,之后来设置其他的子属性。比如说tabBarLabel设置每个tab的标题,tabBarIcon设置选中和非选中的图片。
      之后再设置其它每个tab共同的属性,用一个对象表示。
    const Tab = TabNavigator({
      Home:{
        screen:HomeScreen,
        navigationOptions:({navigation}) => ({
          tabBarLabel:'首页',
          tabBarIcon:({focused,tintColor}) => (
              <TabBarItem
                  tintColor={tintColor}
                  focused={focused}
                  normalImage={require('./imgs/ic_like_sel.png') }
                  selectedImage={require('./imgs/ic_mine_sel.png')}
              />
          )
        }),
      },
    
      Mine:{
        screen:MineScreen,
        navigationOptions:({navigation}) => ({
          tabBarLabel:'我',
          tabBarIcon:({focused,tintColor}) => (
              <TabBarItem
                  tintColor={tintColor}
                  focused={focused}
                  normalImage={require('./imgs/ic_like_sel.png')}
                  selectedImage={require('./imgs/ic_like_sel.png')}
              />
          )
        }),
      },
    },
    
        {
          tabBarComponent:TabBarBottom,
          tabBarPosition:'bottom',
          swipeEnabled:false,
          animationEnabled:false,
          lazy:true,
          tabBarOptions:{
            activeTintColor:'#06c1ae',
            inactiveTintColor:'#979797',
            style:{backgroundColor:'#ffffff',},
            labelStyle: {
              fontSize: 20, // 文字大小
            },
          }
    });
    
    • 将tab放入到Navigator中
    const Navigator = StackNavigator(
        {
            Tab:{screen:Tab},
    
        },
    
        {
            navigationOptions:{
                // title:'首页',
                headerBackTitle:null,
                headerTintColor:'#333333',
                showIcon:true,
                swipeEnabled:false,
                animationEnabled:false,
            },
    
            mode:'card',
        });
    
    • 在render方法中返回导航组件
    export default class App extends Component<{}> {
      render() {
        return (
         <Navigator/>
        );
      }
    }
    
    • HomePage和MinePage的代码

    StackNavigator还提供了onNavigationStateChange回调方法,用来监听导航状态的改变

    import React, { Component } from 'react';
    import {
        Platform,
        StyleSheet,
        Text,
        View
    } from 'react-native';
    export default class HomePage extends Component {
    
        static navigationOptions = {
            title:'首页',
        };
    
        render() {
            return(
                <View style={{flex:1,backgroundColor:'yellow'}}>
                    <Text onPress={this._skip.bind(this)}>点击跳转</Text>
                </View>
            );
        }
    
        _skip() {
            this.props.navigation.navigate("Mine");
        }
    }
    
    import React, { Component } from 'react';
    import {
        Platform,
        StyleSheet,
        Text,
        View
    } from 'react-native';
    export default class MinePage extends Component {
    
        static navigationOptions = {
            title:'我',
        };
    
        render() {
            return(
                <View style={{flex:1,backgroundColor:'pink'}}>
                    <Text onPress={this._skip.bind(this)}>MinePage</Text>
                </View>
            );
        }
    
        /**
         * 跳转
         */
        _skip() {
            this.props.navigation.goBack();
        }
    }
    
    效果图

    2.3DreawerNavigator抽屉导航

    DrawerNavigator是一个抽屉导航。设置方式其实跟设置Tab差不多。只是需要设定某些特殊的属性。比如说drawerLabel、drawerIcon、drawerWidth、drawerPosition等等。

    • 定义抽屉导航
      HomeScreen与MineScree是导入外界的两个界面,将它们定义到DrawerNavigator中。在抽屉导航中,将组件的属性也一起设置好。
    import {DrawerNavigator} from 'react-navigation';
    import HomeScreen from './Pages/HomePage';
    import MineScreen from './Pages/MinePage';
    
    const MyApp = DrawerNavigator({
        Home: {
            screen: HomeScreen,
        },
        Mine: {
            screen:MineScreen,
        },
    },
        {
            drawerWidth: 200, // 抽屉宽
            drawerPosition: 'left', // 抽屉在左边还是右边
            contentOptions: {
                initialRouteName: 'Home', // 默认页面组件
                activeTintColor: 'white',  // 选中文字颜色
                activeBackgroundColor: '#ff8500', // 选中背景颜色
                inactiveTintColor: '#666',  // 未选中文字颜色
                inactiveBackgroundColor: '#fff', // 未选中背景颜色
                style: {  // 样式
    
                }
            }
        }
    );
    
    • 在render方法中返回抽屉组件
    export default class App extends Component<{}> {
        // static navigationOptions={
        //     title:'app',
        //     gesturesEnabled:false,
        //     header:null,
        // }
    
        render() {
            return (
                <View style = {{flex:1,marginTop:20,}}>
    
                    <MyApp />
                </View>
            );
        }
    }
    
    • 设置HomePage子页面的属性
      一旦加入了导航组件react-navigation,那么其页面就会有navigationOptions属性。我们可以在这个属性里面设置抽屉导航的样式。
    export default class HomePage extends Component<{}> {
        static navigationOptions = {
            drawerLabel: 'Home',
            drawerIcon: ({ tintColor }) => (
                <Image
                    source={require('.././imgs/ic_like_sel.png')}
                    style={[styles.icon, {tintColor: tintColor}]}
                />
            ),
        };
    }
    
    • 返回HomePage页面要展示的组件
      用navigation的navigate属性可以跳转到指定的页面。如果指定的是DrawerOpen,意思就是打开抽屉。
    render() {
            return (
                <View>
                    <Button
                        onPress={() => this.props.navigation.navigate('Mine')}
                        title="Go to Mine"
                    />
                    <Button
                        onPress={()=>this.props.navigation.navigate('DrawerOpen')}
                        title="open the draw"
                    />
                </View>
            );
        }
    
    • 设置样式
    const styles = StyleSheet.create({
        icon: {
            width: 24,
            height: 24,
        },
    });
    
    • 设置MinePage页面
      MinePage页面和HomePage页面相差不大。只是做代码演示而已,这里不再阐述
    import React, { Component } from 'react';
    import {
        Platform,
        StyleSheet,
        Text,
        View,
        Image,
        Button
    } from 'react-native';
    export default class MineScreen extends Component<{}> {
        static navigationOptions = {
            drawerLabel: 'Mine',
            drawerIcon: ({ tintColor }) => (
                <Image
                    source={require('.././imgs/ic_mine_sel.png')}
                    style={[styles.icon, {tintColor: tintColor}]}
                />
            ),
        };
    
        render() {
            return (
                <View>
                    <Button
                        onPress={() => this.props.navigation.goBack()}
                        title="Go back home"
                    />
    
                    <Button
                        onPress={()=>this.props.navigation.navigate('DrawerOpen')}
                        title="open the draw"
                    />
                </View>
            );
        }
    }
    const styles = StyleSheet.create({
        icon: {
            width: 24,
            height: 24,
        },
    });
    

    效果图如下:

    效果图

    非宁静无以致远,非淡泊无以明志。在学习的道路上,多少会遇到泥泞挫折。我可以放慢脚步,但绝能不回头,我的梦想,在路上。

    相关文章

      网友评论

        本文标题:react-navigation,刷新你的导航

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