这一章我参考的资源很多,官网的navigator、navigation、UIExplorer的navigatorExample,因此会涉及到非常多的es6语法,尽量一一记录下来。
最小化代码
import React,{Component} from 'react'; import SplashScreen from 'react-native-splash-screen'; import {AppRegistry,Text,Navigator} from 'react-native'; const sleep = require('es6-sleep').promise; export default class NavAllDay extends Component { async sleep(milliansecond) { await sleep(milliansecond); } async componentDidMount() { // do anything while splash screen keeps,use await to wait for an async task. await sleep(2000); await SplashScreen.hide(); } render() { return (<Navigator initialRoute={{ title: 'Awesome Scene',index: 0 }} renderScene={(route,navigator) => <Text>Hello {route.title}!</Text> } style={{padding: 100}}/> ); } } AppRegistry.registerComponent('rn_practice',() => NavAllDay);
Navigator参数:initialRoute
: 类似MVC框架中的urls这一层,表明当前这个Navigator有多少个路径,每个路径表示一个可切换的场景。renderScene
: 类似MVC框架中的template这一层,每次触发场景切换时将定义的变量传递过来进行重新渲染。
备注: 上面这段代码不会有任何很直观的效果,因为只有一个route,没有切换,因此感觉不出来它的特性,下面逐量去增加代码。
两条路由
import React,Navigator,TouchableHighlight} from 'react-native'; const sleep = require('es6-sleep').promise; export default class NavAllDay extends Component { async sleep(milliansecond) { await sleep(milliansecond); } async componentDidMount() { // do anything while splash screen keeps,use await to wait for an async task. await sleep(2000); await SplashScreen.hide(); } render() { const routes = [ {title: 'First Scene',index: 0},{title: 'Second Scene',index: 1} ]; return (<Navigator initialRoute={routes[0]} renderScene={ (route,navigator) => <Text onPress={() => { if (route.index == 0) { navigator.push(routes[route.index+1]) } else { navigator.pop() }} }> Hello {route.title} ! </Text> } /> ); } } AppRegistry.registerComponent('rn_practice',() => NavAllDay);
备注: 这里利用了Text组件的onPress来触发状态的切换,也就是说当我点击这个文本内容时,就会切换到另外一个文本。
多条路由
import React,{Component,PropTypes} from 'react'; import SplashScreen from 'react-native-splash-screen'; import {View,TouchableHighlight,AppRegistry,Navigator} from 'react-native'; const sleep = require('es6-sleep').promise; export default class MyScene extends Component { render() { return ( <View> <Text>Current Scene: {this.props.title}</Text> <Text onPress={this.props.onForward}>Tap me to load the next scene</Text> <Text onPress={this.props.onBack}>Tap me to go back</Text> </View> ) } } MyScene.propTypes = { title: PropTypes.string.isrequired,onForward: PropTypes.func.isrequired,onBack: PropTypes.func.isrequired,}; class SimpleNavigationApp extends Component { async sleep(milliansecond) { await sleep(milliansecond); } async componentDidMount() { // do anything while splash screen keeps,use await to wait for an async task. await sleep(2000); await SplashScreen.hide(); } render() { return ( <Navigator initialRoute={{ title: 'My Initial Scene',index: 0 }} renderScene={(route,navigator) => <MyScene title={route.title} onForward={() => { const nextIndex = route.index + 1; navigator.push({ title: 'Scene ' + nextIndex,index: nextIndex,}); }} onBack={() => { if (route.index > 0) { navigator.pop(); } }} /> } /> ) } } AppRegistry.registerComponent('rn_practice',() => SimpleNavigationApp);
propTypes
是用来声明当前对象所需要的参数类型和是否必填,一般用于开发调试(注释掉不影像任何功能),线上产品不要使用propTypes因为它会影像性能和提出警告,官方详细说明。MyScene
这个对象内容很简单,直接就返回一个View里面包裹这三个Text,在react中,它会将MyScene当作一个组件对象,可以直接用在JSX中,例如<MyScene />。
备注: 在这个例子中,并没有提前定义总共有多少个routes,只定义了initialRoute的数据格式,然后所有的操作都在renderScene里面去动态的控制,也就是说通过这种方式可以无限点击和无限操作。
装饰(宽和高)--多条路由
import React,StyleSheet} from 'react-native'; const sleep = require('es6-sleep').promise; export default class MyScene extends Component { render() { return ( <View> <View style={styles.row_title}> <Text>Current Scene: {this.props.title}</Text> </View> <View style={styles.row_items}> <Text onPress={this.props.onForward}>Tap me to load the next scene</Text> </View> <View style={styles.row_items}> <Text onPress={this.props.onBack}>Tap me to go back</Text> </View> </View> ) } } class SimpleNavigationApp extends Component { async sleep(milliansecond) { await sleep(milliansecond); } async componentDidMount() { // do anything while splash screen keeps,}); }} onBack={() => { if (route.index > 0) { navigator.pop(); } }} /> } configureScene={(route,navigator) => Navigator.SceneConfigs.HorizontalSwipeJump} /> ) } } const styles = StyleSheet.create({ row_items: { padding: 20,borderBottomWidth: 1 / 3,borderBottomColor:'#CDCDCD',},row_title: { height: 50,justifyContent: 'center',alignItems: 'center' } }); AppRegistry.registerComponent('rn_practice',() => SimpleNavigationApp);
StyleSheet
加点样式跟没有样式,确实不一样哈,好看多了。configureScene
这是Navigator组件其中的一个参数,它的用途是配置切换的效果,这里列出了可配置范围。
- Navigator.SceneConfigs.PushFromRight (default)
- Navigator.SceneConfigs.FloatFromRight
- Navigator.SceneConfigs.FloatFromLeft
- Navigator.SceneConfigs.FloatFromBottom
- Navigator.SceneConfigs.FloatFromBottomAndroid
- Navigator.SceneConfigs.FadeAndroid
- Navigator.SceneConfigs.SwipeFromLeft
- Navigator.SceneConfigs.==HorizontalSwipeJump== # 这个牛逼,采用这个配置之后,在屏幕任意地方左划或又划分别标识前进和后退,但是前提是要存在多个routes,否则划不过去。
- Navigator.SceneConfigs.HorizontalSwipeJumpFromRight
- Navigator.SceneConfigs.HorizontalSwipeJumpFromLeft
- Navigator.SceneConfigs.VerticalUpSwipeJump
- Navigator.SceneConfigs.VerticalDownSwipeJump
装饰(material circle)--多条路由
import React,StyleSheet,TouchableNativeFeedback} from 'react-native'; const sleep = require('es6-sleep').promise; export default class MyScene extends Component { render() { return ( <View> <View style={styles.row_title}> <Text>Current Scene: {this.props.title}</Text> </View> <TouchableNativeFeedback background={TouchableNativeFeedback.SelectableBackground()} onPress={this.props.onForward}> <View style={styles.row_items}> <Text> Enabled TouchableNativeFeedback </Text> </View> </TouchableNativeFeedback> <TouchableNativeFeedback background={TouchableNativeFeedback.SelectableBackground()} onPress={this.props.onBack}> <View style={styles.row_items}> <Text>Tap me to go back</Text> </View> </TouchableNativeFeedback> </View> ) } } class SimpleNavigationApp extends Component { async sleep(milliansecond) { await sleep(milliansecond); } async componentDidMount() { // do anything while splash screen keeps,alignItems: 'center' },}); AppRegistry.registerComponent('rn_practice',() => SimpleNavigationApp);
腾讯新闻APP中的新闻列表,当我长按某一条新闻列表是,会出现一个底色为灰色的圆圈慢慢扩大一直灰色到把整行给覆盖掉,这个特性采用的是TouchableNativeFeedback
,是google的material设计风格。
注意: 我在调试这个功能,代码已经写好了但是一直都没有出现NativeFeedback这个特效,反复折腾了好久才发现原来是我在Text组件中用了onPress,导致与TouchableNativeFeedback相互冲突了,所以我把Text中的onPress移除掉,将相关的状态切换代码写到TouchableNativeFeedback组件的onPress中。
两个navigator
一个是导航,另外一个是列表