react-navigation,刷新你的导航

在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,
    },
});

效果图如下:

效果图

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

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • react-navigation导航组件使用详解 注意了,如果有小伙伴们发现运行作者提供的react-naviga...
    光强_上海阅读 23,296评论 38 103
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,629评论 1 92
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,615评论 4 59
  • 其实,要想成为有钱人其实很简单:当你身边都是有钱人的时候,你也一定会成为有钱人。 美国前总统克林顿原来是吹萨卡斯...
    她极美的灵魂阅读 2,065评论 0 2