主界面开发

上一节,我们已经完成了首页的开发,现在,我们继续完成主界面的开发,就是添加底部‘首页’和‘我的’两个tabbar。

在js/文件夹下,新建MainScene.js文件

import React,{Component} from 'react';
import {View,Text,TouchableOpacity,Image,StyleSheet,
}from 'react-native';export default class MainScene extends Component{constructor(props){super(props);this.state={tabIndex:0,}}render(){return(<View style={{flex:1,justifyContent:'flex-end'}}><View style={{backgroundColor:'#d5d5d5',height:1,}}/><View style={{height:55,flexDirection:'row',justifyContent:'center',alignItems:'center'}}><TouchableOpacity style={{flex:1}} activeOpacity={0.6} onPress={this._onTabPress.bind(this,0)}><View style={styles.ItemView}><Image
                                style={{height:30,width:30}}source={this.state.tabIndex==0?require('../img/icon_home_select.png'):require('../img/icon_home_unselect.png')}/><Text style={this.state.tabIndex==0?styles.TabTextSelect:styles.TabTextUnSelect}>首页</Text></View></TouchableOpacity><TouchableOpacity style={{flex:1}} activeOpacity={0.6} onPress={this._onTabPress.bind(this,1)}><View style={styles.ItemView}><Image
                                style={{height:30,width:30}}source={this.state.tabIndex==0?require('../img/icon_my_unselect.png'):require('../img/icon_my_select.png')}/><Text style={this.state.tabIndex==0?styles.TabTextUnSelect:styles.TabTextSelect}>我的</Text></View></TouchableOpacity></View></View>);}//tab点击事件_onTabPress(index){
//console.log('index = '+ index);//this.viewPager.setPage(index);this.setState({tabIndex:index,});}}
var styles = StyleSheet.create({ItemView:{flex:1,justifyContent:'center',alignItems:'center',marginTop:3,},TabTextSelect:{flex:1,textAlign:'center',alignItems:'center',color:'#ff5722',},TabTextUnSelect:{flex:1,textAlign:'center',alignItems:'center',color:'#d5d5d5',},
});

主要绘制了,底部两个带图标的选项卡,根据state.tabIndex的索引,动态修改tab的icon和文字样式,然后将index.android.js的启动页修改为MainScene,运行程序,结果如下

然后就是给tab上方添加内容页面

MainScene->render

render(){var page = this.state.tabIndex===0?<HomeScene/>:<MyScene />;return(<View style={{flex:1,justifyContent:'flex-end'}}>{page}...//省略其它代码</View>);
}

这里我们使用动态渲染页面的方式,当选项进行切换时,根据tabIndex索引值,获取到对应的页面进行显示。

ok,添加完之后,运行,现在的效果如下

到此,主界面的功能基本完成,只是点击列表item没反应,因为,我们还没给页面设计跳转功能,下面我们将来说说应用的导航器。

应用导航器

关于react-native页面跳转和数据传递,使用到的是Navigator这个组件。它可以帮我们在在不同的页面进行切换,只要指定了路由,在renderScene方法就会渲染对应的页面。更多详细介绍

由于我们的应用要跳转的地方会有很多,所以我们需要为APP定义一个统一的路由入口。

我们先抽出定义一个应用的导航器AppNavigator,在js/component/下新建AppNavigator.js

import React,{Component} from 'react';
import {Navigator,
} from 'react-native';
//应用导航器
export default class AppNavigator extends Component{constructor(props){super(props);}render(){return(<Navigator initialRoute={{id:this.props.id,data:this.props.data,name:this.props.name,component:this.props.component}}renderScene={(route,navigator)=>{let Scene = route.component;return <Scene id={route.id} data={route.data} name={route.name} navigator={navigator}/>}}style={{flex:1,}}configureScene={(route) => {if(route.sceneConfig){return route.sceneConfig;}return Navigator.SceneConfigs.HorizontalSwipeJump;}}/>);}
}

我们指定了路由数据结构如下(这个数据结构根据自己的需求去定义),

{id:this.props.id,data:this.props.data,name:this.props.name,component:this.props.component
}

页面的唯一识别id,要传递的数据data(可以任意类型的数据),页面的名称name(页面的名称,这里用于TitleBar显示标题名称),要渲染的页面组件component。重要的部分在于renderScene函数。

renderScene={(route,navigator)=>{let Scene = route.component;return <Scene id={route.id} data={route.data} name={route.name} navigator={navigator}/>
}}

这里我们获取到route传过来的component,然后将该component当作一个view节点返回回去,并且给该组件传入了一组props,这样在该Scene下,就可以通过this.props获取到id\data\name\navigaror.当获取到navigaror对象之后,我们可以进行push\pop操作,实现页面的跳转\回退功能。

configureScene函数是配置页面跳转时的动画效果

使用导航器进行页面跳转

导航器写好之后,我们就该思考将它作为应用的统一入口应该放置在哪合适。

如果你在使用Navigator过程中,碰到跳转时,某些元素比如标题、底部的tabbar,在跳转之后还需要特殊处理(隐藏),那么可能是你把Navigator放的位置不够准确。就像我之前写的时候,将Navigator放在了HomeScene中,导致点击影片item页面跳转之后(跳到详情),底部的tabbar还显示着。一开始想的是在跳转之后将tabbar隐藏,但是这样就会有闪动的情况,后来把Navigator位置改正之后,就达到想要的结果了。

既然作为程序的统一路由入口,那么我们是不是有理由这么想,它也应该是放在程序的启动处。是的,将它放在index.android.js。

import AppNavigator from './js/component/AppNavigator';
import MainScene from './js/MainScene';
class XiFan extends Component {render(){return(<AppNavigator id='MainScene' data='' name='' component={MainScene}/>);}
}

将导航器的初始路由页面设置为MainScene,由于是主界面,所以不用传递data\name数据。

然后打开MainScene,修改代码

render(){var page = this.state.tabIndex===0?<HomeScene navigator={this.props.navigator}/>:<MyScene />;....//省略其它代码
}

增加了navigator参数,而this.props.navigator实例对象是来至于AppNavigator的renderScene中navigator,这样我们就把navigator实例对象传递给了HomeScene。再打开HomeScene,要修改的地方有两处

HomeScene->render()

  • 让TitleBar具有返回/回退功能

将navigator对象传递给TitleBar

<TitleBar title="首页" subtitle="看韩剧,上稀饭" subScene={false} navigator={this.props.navigator}/>

再打开TitleBarComponent ->_onIconClick()

//返回按钮事件
_onIconClick(){var navigator = this.props.navigator;if(navigator){navigator.pop();}
}

在获取到navigator对象后,进行pop操作,就可以返回了。

  • 将navigator对象传递给DramaComponent
<ViewPagerAndroid...//省略其它代码
><View style={{flex:1}}><DramaComponent url='/hanju/new/' navigator={this.props.navigator}/></View><View style={{flex:1}}><DramaComponent url='/hanju/renqi/' navigator={this.props.navigator}/></View>
</ViewPagerAndroid>

这样DramaComponent也有了navigator实例对象,打开DramaComponent,我们给它item点击事件添加跳转到详情的功能。

DramaComponent -> _onItemPress

//item 点击跳转
_onItemPress(movie){const navigator = this.props.navigator;if(navigator){navigator.push({id:'DramaDetailScene',data:movie,name:movie.name,component:DramaDetailScene});}
}

也就是,如果是由Navigator导航的组件,那么该组件本身就有Navigator对象,并由this.props.navigator取得,如果是导航组件的内部组件要使用导航对象,那么就要给该组件增加props属性

navigator={this.props.navigator}

这里item点击跳转的是详情页DramaDetailScene,我们先简单的写下这个页面,后面在具体实现详情页

新建DramaDetailScene.js

import React,{Component} from 'react';
import {View,Text
} from 'react-native';
import TitleBar from './component/TitleBarComponent';
export default class DramaDetailScene extends Component{constructor(props) {super(props);}render(){return (<View><TitleBar title={this.props.name} subtitle='' subScene={true} navigator={this.props.navigator}/><Text>影片详情页</Text></View>);};
}

这样,我们就实现了页面的跳转功能,但是由于Android还有物理返回键,因此要实现按下返回键时退出当前页、在主界面 “再按一次退出程序” 的功能。

首先要拦截返回键事件,在主界面MainScene,添加如下代码

import {...//省略其它代码BackAndroid,Platform,ToastAndroid
} from 'react-native';export default class MainScene extends Component{...//省略其它代码componentDidMount(){this._addBackAndroidListener(this.props.navigator);}componentWillUnmount(){this._removeBackAndroidListener();}//监听Android返回键_addBackAndroidListener(navigator){if(Platform.OS==='android'){var currTime = 0;BackAndroid.addEventListener('hardwareBackPress',()=>{if(!navigator){return false;}const routers = navigator.getCurrentRoutes();if(routers.length == 1){//在主界面var nowTime = (new Date()).valueOf();if(nowTime - currTime > 2000){currTime = nowTime;ToastAndroid.show("再按一次退出程序",ToastAndroid.SHORT);return true;}return false;}else{//在其他子页面navigator.pop();return true;}});}}//移除监听_removeBackAndroidListener(){if (Platform.OS === 'android') {BackAndroid.removeEventListener('hardwareBackPress');}}
}

总结

至此,应用的页面跳转已经实现了,navigator对于react native 来说还是比较重要的一个组件,因为每个应用都会涉及到页面的切换,而这都离不开对navigator的使用。看完本节的内容,应该对navigator的使用已经掌握得差不多了,下一节,我们将对详情页进行开发,其中重要的是学习如何使用原生代码为react native提供原生能力。

【稀饭】react native 实战系列教程之Navigator实现页面跳转相关推荐

  1. 【稀饭】react native 实战系列教程之完成首页

    首页功能 前面,我们已经完成了影视信息组件的开发,接下来,我们要用该组件来完成首页界面功能的开发,如下图 可以看到,首页顶部一个标题栏,下面是'最新'.'最热'两个选项卡.我们要完成的有标题栏.选项卡 ...

  2. 【稀饭】react native 实战系列教程之首页列表UI实现

    首页设计与实现 首先,这章节讲的是首页内容的设计与实现,不包括主界面的设计,因为一开始入手,我希望能立马获取到数据并能展示出来,后面再来搭木积似的一步一步把整体框架做起来. 设计 (图丑,莫见怪~) ...

  3. 【稀饭】react native 实战系列教程之自定义原生模块

    影片详情开发也是通过Cheerio抓取并分析网页获取到的详情数据,本节就不作为详细内容来讲解了,详细的代码可以看下我的github,效果如下: 在点击播放时,会跳转到播放界面,并且横屏显示,退出播放界 ...

  4. [置顶] 【稀饭】react native 实战系列教程之热更新原理分析与实现

    很多人在技术选型的时候,会选择RN是因为它具有热更新,而且这是它的一个特性,所以实现起来会相对比较简单,不像原生那样,原生的热更新是一个大工程.那就目前来看,RN的热更新方案已有的,有微软的CodeP ...

  5. react native 实战系列教程之热更新原理分析与实现

    很多人在技术选型的时候,会选择RN是因为它具有热更新,而且这是它的一个特性,所以实现起来会相对比较简单,不像原生那样,原生的热更新是一个大工程.那就目前来看,RN的热更新方案已有的,有微软的CodeP ...

  6. 后盾vip php框架,后盾网实战VIP教程之ThinkPHP微博项目系列培训

    php教程 当前位置:主页 > php教程 > 后盾网实战VIP教程之ThinkPHP微博项目系列培训 后盾网实战VIP教程之ThinkPHP微博项目系列培训 教程大小:1.56GB   ...

  7. 手把手教React Native实战开发视频教程 干货

    手把手教React Native实战开发视频教程[更新到70集啦...] ================================ 由于360云盘关闭,作者已经将资源迁移.需要的朋友请访问一下 ...

  8. 菜鸟窝Android百度云视频,菜鸟窝React Native 视频系列教程

    菜鸟窝React Native 视频系列教程 交流QQ群:276960232 Hi,我是RichardCao,现任新美大酒店旅游事业群的Android Developer.15年加入饿了么即时配送BU ...

  9. java jdbc 教程_java JDBC系列教程之JDBC类的简析与JDBC的基础操作

    什么是JDBC? 概念:JAVA Database Connectivity Javas数据库连接,Java语言操作数据库接口,然后由各个数据库厂商去实现这个接口,提供数据库驱动java包,我们可以使 ...

最新文章

  1. SyntaxError: Non-ASCII character ‘\xe4‘ in file xx(路径)
  2. python面试常见问题-Python面试中最常见的25个问题
  3. Java面试进阶:Dubbo、Zookeeper面试题锦集
  4. 介绍计算机硬件的情景剧表演,手忙脚乱的情景剧
  5. e_msg_c_gs_enter_gs_req
  6. 你应该了解的python 垃圾回收机制
  7. 4999元起!iQOO 9 Pro赛道版上架:迄今为止成本最高手机后盖
  8. Linux学习笔记003----linux yum命令详解
  9. VS2013 启用 angularjs 智能提示 Intelligence
  10. 安装依赖以及页面解析
  11. Qt QDir 递归获取文件夹中的所有文件
  12. 【Antd】rawData.some is not a function 报错解决方法
  13. 【老骥伏枥-狗年大礼包】嵌入式linux逆向工程,手把手教你作黑Q-第一讲
  14. android so 瘦身,Android APK 瘦身实践
  15. Log:Spdlog初探(1)
  16. 怎样把网上的短信发送到手机
  17. c语言统计出现个数,C语言统计数字出现的个数
  18. vue的provide的使用
  19. 卫星导航之如何画出常见的图形世界地图、多路径、天空图等
  20. 三星 android 模拟器下载地址,GalaxyOfWar电脑版下载 安卓模拟器图文安装教程

热门文章

  1. FPGA视频拼接器的DP 的4k 功能输入, 把lvds 转为 serdes
  2. 微信电脑端多开操作 要开多少台就有多少台(电脑小白都会)
  3. 初始C语言——梦开始的地方
  4. flarum编辑器预览插件
  5. Flink parallelism 和 Slot 介绍
  6. ZYNQ7000 (二十)等精度频率计的原理分析和实例实现
  7. Oracle数据表导入导出_数据迁移用
  8. 华为官方出品:首本HMS Core技术解析图书问世
  9. P2P通信基本原理与实现
  10. MYSQL 校队规则