参考资料:React Navigationhtml
react-native-tab-navigator的使用传送门node
在目前市面上的APP中,大部分都是选项与选项之间的切换,好比:微信、微博、QQ空间......, 在iOS中,咱们能够经过TabItem类进行实现。那么,在React Native中,咱们应该怎么实现呢?react
在React Native中能够经过TabBarIOS和TabBarIOS.Item组件来实现选项卡切换效果,你们能够看到后面带有IOS,因此这个组件是不支持Android的,固然后面咱们能够自定义该组件。ios
1、TabBarIOS常见的属性git
View的全部属性均可以被继承github
barTintColor color 设置tab条的背景颜色npm
tintColor color 设置tab条上被选中图标的颜色json
translucent bool 设置Tab栏是否是半透明的效果react-native
2、TabBarIOS.Item常见的属性数组
badge number
在图标的右上方显示小红色气泡,显示信息
icon Image.propTypes.source
Tab按钮自定义的图标,若是systemicon属性被定义了,那么该属性会被忽略
onPress function
当Tab按钮被选中的时候进行回调,你能够设置selected={true}来设置组件被选中
selected bool
该属性标志子页面是否可见,若是是一个空白的内容页面,那么必定是忘记了选中任何的一个页面标签Tab
selectedIcon Image.propTypes.source
设置当Tab按钮被选中的时候显示的自定义图标,若是systemIcon属性被设置了,那么该属性会被忽略。若是定义了icon属性,可是当前的selectedIcon属性没有设置,那么该图标会被设置成蓝色
style 设置样式风格,继承View的样式各类风格
systemIcon
enum('bookmarks','contacts','downloads','favorites','featured','history','more','most-recent','most-viewed','recents','search','top-rated')
系统预约义的图标,若是你使用这些图标,那么你上面设置的标题,选中的图标都会被这些系统图标所覆盖。
title string
在Tab按钮图标下面显示的标题信息,若是你设置了SystemIcon属性,那么该属性会被忽略
3、TabBarIOS.Item案例展现
代码展现:
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, Image, TabBarIOS } from 'react-native'; var Car = require('./Car.json'); export default class FListViewDemo1 extends Component{ constructor(props){ super(props); this.state = { selectedTabBarItem:'home' }; } render(){ return( <View style={styles.container}> <View style={styles.headerViewStyle}> <Text style={{color:'white'}}>Tab选项卡切换</Text> </View> <TabBarIOS barTintColor='white'> <TabBarIOS.Item systemIcon="contacts" badge="3" // title="张三" selected={this.state.selectedTabBarItem == 'home'} onPress ={()=>{this.setState({selectedTabBarItem:'home'})}} > <View style={[styles.commentViewStyle,{backgroundColor:'red'}]}> <Text>首页</Text> </View> </TabBarIOS.Item> <TabBarIOS.Item systemIcon="bookmarks" // title="李四" selected={this.state.selectedTabBarItem == 'second'} onPress ={()=>{this.setState({selectedTabBarItem:'second'})}} > <View style={[styles.commentViewStyle,{backgroundColor:'green'}]}> <Text>第二页</Text> </View> </TabBarIOS.Item> <TabBarIOS.Item systemIcon="contacts" // title="王二" selected={this.state.selectedTabBarItem == 'third'} onPress ={()=>{this.setState({selectedTabBarItem:'third'})}} > <View style={[styles.commentViewStyle,{backgroundColor:'blue'}]}> <Text>第三页</Text> </View> </TabBarIOS.Item> <TabBarIOS.Item systemIcon="contacts" // title ="麻子" selected={this.state.selectedTabBarItem == 'four'} onPress ={()=>{this.setState({selectedTabBarItem:'four'})}} > <View style={[styles.commentViewStyle,{backgroundColor:'purple'}]}> <Text>第四页</Text> </View> </TabBarIOS.Item> </TabBarIOS> </View> ); } } const styles = StyleSheet.create({ headerViewStyle:{ height:64, backgroundColor:'black', justifyContent:'center', alignItems:'center' }, commentViewStyle:{ flex:1, alignItems:'center', justifyContent:'center' }, container:{ flex:1, backgroundColor:'#f5fcff' } });
提示:在TabBarIOS.Item中,若是设置了systemIcon,再去设置title将不会起做用。
在开发中,咱们须要实现多个界面的切换,这时候就须要一个导航控制器来进行各类效果的切换。那么,在React Native中有两个组件可以实现这样的效果:Navigator和NavigatorIOS。
其中Navigator是适配Android和iOS,而NavigatorIOS则是包装了UIKit的导航功能,可使用左划功能来返回到上一界面。
提示:报错:'Navigator is deprecated and has been removed from this package. It can now be installed ' +
'and imported from `react-native-deprecated-custom-components` instead of `react-native`. ' +
'Learn about alternative navigation solutions at http://facebook.github.io/react-native/docs/navigation.html'
这是由于版本升级到0.43以上的话,Navigator不能直接从react-native里面获取了,
解决方案:
npm install react-native-deprecated-custom-components --save
而后在引用的地方
import {Navigator} from 'react-native-deprecated-custom-components'
1、Navigator
不少时候,咱们须要导航器来应对不一样场景(页面)间的切换。它经过路由对象来分辨不一样的场景,咱们这里采用的就是 renderScene
方法,根据指定的路由来渲染。
1.1 经常使用的属性
initialRoute ={{ name: 'home', component: HomeScene }}
这个指定了默认的页面,也就是启动的组件页面
configureScene ={() => {
return Navigator. SceneConfigs .HorizontalSwipeJump;
}}
页面之间跳转时候的动画手势,能够看这个目录:node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js(能够看其余跳转的时候的方向),好比:PushFromRight FloatFromRight FloatFromLeft FloatFromBottom FloatFromBottomAndroid FadeAndroid HorizontalSwipeJump HorizontalSwipeJumpFromRight VerticalUpSwipeJump VerticalDownSwipeJump等等。
renderScene
具体是方法以下:(route, navigator) =><MySceneComponent title={route.title} navigator={navigator} />
两个参数中的route包含的是initial的时候传递的name和component,而navigator是一个咱们须要用的Navigator的对象;
因此当咱们拿到route中的component的时候,咱们就能够将navigator传递给它,正由于如此,咱们的组件HomeScene才能够经过 this.props.navigator,拿到路由。
initialRouteStack [object] 参数对象数组
这是一个初始化的路由数组进行初始化。若是initalRoute属性没有设置的话,那么就必须设置initialRouteStack属性,使用该最后一项做为初始路由。 若是initalRouteStack属性没有设置的话,该会生成只包含initalRoute值的数组
navigationBar node
该为可选的参数,在页面切换中用来提供一个导航栏
navigator object
该为可选参数,能够从父类导航器中获取导航器对象
sceneStyle 样式风格
该继承了View视图的全部样式风格,用于设置每一个页面容器的风格
1.2 经常使用的导航器方法
当获取了导航器对象的引用,咱们能够进行调用如下一些方法来实现页面导航功能:
getCurrentRoutes() 该进行返回存在的路由列表信息
jumpBack() 该进行回退操做 可是该不会卸载(删除)当前的页面
jumpForward() 进行跳转到至关于当前页面的下一个页面
jumpTo(route) 根据传入的一个路由信息,跳转到一个指定的页面(该页面不会卸载删除)
push(route) 导航切换到一个新的页面中,新的页面进行压入栈。经过jumpForward()方法能够回退过去
pop() 当前页面弹出来,跳转到栈中下一个页面,而且卸载删除掉当前的页面
replace(route) 只用传入的路由的指定页面进行替换掉当前的页面
replaceAtIndex(route,index) 传入路由以及位置索引,使用该路由指定的页面跳转到指定位置的页面
replacePrevious(route) 传入路由,经过指定路由的页面替换掉前一个页面
resetTo(route) 进行导航到新的界面,而且重置整个路由栈
immediatelyResetRouteStack(routeStack) 该经过一个路由页面数组来进行重置路由栈
popToRoute(route) 进行弹出相关页面,跳转到指定路由的页面,弹出来的页面会被卸载删除
popToTop() 进行弹出页面,导航到栈中的第一个页面,弹出来的全部页面会被卸载删除
1.3 默认写法
<Navigator initialRoute={{ name: defaultName, component: defaultComponent }} configureScene={(route) => { return Navigator.SceneConfigs.HorizontalSwipeJumpFromRight; }} renderScene={(route, navigator) => { let Component = route.component; return <Component {...route.props} navigator={navigator} /> }} />
2、Navigator.IOS
NavigatorIOS包装了UIKit的导航功能,可使用左划功能来返回到上一界面。
2.1 经常使用的导航器方法
push(route)
导航器跳转到一个新的路由。
pop()
回到上一页。
popN(n)
回到N页以前。当N=1的时候,效果和 pop() 同样。
replace(route)
替换当前页的路由,并当即加载新路由的视图。
replacePrevious(route)
替换上一页的路由/视图。
replacePreviousAndPop(route)
替换上一页的路由/视图而且马上切换回上一页。
resetTo(route)
替换最顶级的路由而且回到它。
popToRoute(route)
一直回到某个指定的路由。
popToTop()
回到最顶层的路由。
2.2 经常使用的属性
barTintColor string
导航条的背景颜色。
initialRoute {
component: function, // 路由到对应的版块
title: string, // 标题
passProps: object, // 传递的参数
backButtonIcon: Image.propTypes.source, // 返回按钮
backButtonTitle: string, // 返回按钮标题
leftButtonIcon:Image.propTypes.source,
leftButtonTitle: string,
onLeftButtonPress: function,
rightButtonIcon: Image.propTypes.source,
rightButtonTitle: string,
onRightButtonPress: function,
wrapperStyle: [object Object]
}
NavigatorIOS使用"路由"对象来包含要渲染的子视图、它们的属性、以及导航条配置。"push"和任何其它的导航函数的参数都是这样的路由对象。
好比:下面新闻列表跳转到新闻详情页详情页:
itemWrapperStyle View#style
导航器中的组件的默认属性。一个常见的用途是设置全部页面的背景颜色。
navigationBarHidden bool
一个布尔值,决定导航栏是否隐藏。
shadowHidden bool
一个布尔值,决定是否要隐藏1像素的阴影。
tintColor string
导航栏上按钮的颜色。
titleTextColor string
导航器标题的文字颜色。
translucent bool
一个布尔值,决定是否导航条是半透明的。
3、综合小案例
3.1 部分核心代码
React Navigation 源于 React Native 社区对一个可扩展且易于使用的导航解决方案的需求,它彻底使用 JavaScript 编写(所以你能够阅读并理解全部源码)。
在你的 React Native 项目中安装react-navigation
这个包
yarn add react-navigation
# or with npm # npm install --save react-navigation
而后,安装 react-native-gesture-handler。 若是你使用 Expo,就什么都不须要作,他已经包含在 SDK 中 了, 不然:
yarn add react-native-gesture-handler
# or with npm # npm install --save react-native-gesture-handler
Link 全部的原生依赖
react-native link react-native-gesture-handler
官方文档:https://reactnavigation.org/docs/zh-Hans/getting-started.html
实例代码:
// In App.js in a new project import React,{Component} from "react"; import { View, Text, Button, Image } from "react-native"; import { createStackNavigator, createAppContainer } from "react-navigation"; //使用自定义组件替换标题 class LogoTitle extends Component{ render(){ return( <Image source={require('./img/img_02.png')} style={{width:30,height:30}} /> ); } } class ThreeScreen extends Component{ static navigationOptions ={ title:'ThreeScreen' }; render(){ return( <View style={{flex:1,alignItems:'center',justifyContent:'center'}}> <Text>ThressScreen</Text> </View> ); } } class DetailsScreen extends Component{ static navigationOptions=({navigation})=>{ return{ title:navigation.getParam('otherParam','A Nested Details Screen') }; }; render(){ const {navigation} = this.props; const itemId = navigation.getParam('itemId','NO-ID'); const otherParam = navigation.getParam('otherParam','some default value'); return( <View style={{flex:1,alignItems:'center',justifyContent:'center'}}> <Text>DetailsScreen</Text> <Text>itemId:{JSON.stringify(itemId)}</Text> <Text>otherParam:{JSON.stringify(otherParam)}</Text> <Button title="Go to Details... again" onPress={()=>this.props.navigation.navigate('Three',{ itemId:Math.floor(Math.random()*100) }) } /> <Button title="Update the title" onPress={()=>this.props.navigation.setParams({otherParam:'Update!'})} /> </View> ); } } class HomeScreen extends Component { static navigationOptions={ headerTitle:<LogoTitle/>, headerRight:( <Button onPress={()=>alert('this is a button!')} title = "info" color ="#fff" /> ), }; render() { return ( <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}> <Text>Home Screen</Text> <Button title="Go to Details" onPress={()=>{this.props.navigation.navigate('Details',{ itemId:86, otherParam:'anything you want here' }); }} /> </View> ); } } const AppNavigator = createStackNavigator( { Home:HomeScreen, Details:DetailsScreen, Three:ThreeScreen }, { initialRouteName:"Home", defaultNavigationOptions:{ headerStyle:{ backgroundColor:'#fdd000' }, headerTintColor:'#fff', headerTitleStyle:{ fontWeight:'bold' } } } ); export default createAppContainer(AppNavigator);
import React,{Component} from 'react'; import { Text, View,Button,AppRegistry,StyleSheet,Image} from 'react-native'; import Ionicons from 'react-native-vector-icons/Ionicons'; import { createBottomTabNavigator, createStackNavigator, createAppContainer, } from 'react-navigation'; class FiveScreen extends Component{ static navigationOptions={ title:'FiveScreen', headerBackTitle:null }; render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>FiveScreen!</Text> </View> ); } } class FourScreen extends Component{ static navigationOptions={ title:'FourScreen', headerBackTitle:null }; render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>FourScreen!</Text> </View> ); } } class DetailsScreen extends React.Component { static navigationOptions={ title:'DetailsScreen', headerBackTitle:null }; render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Details!</Text> <Button title = "Go to FourScreen" onPress={()=>this.props.navigation.navigate('Four')} /> </View> ); } } class HomeScreen extends React.Component { static navigationOptions={ title:'HomeScreen', headerBackTitle:null, headerRight:( <Button title = "info" color = 'black' onPress = {()=>this.props.navigation.navigate('Five')} /> ) }; render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> {/* other code from before here */} <Button title="Go to Details" onPress={() => this.props.navigation.navigate('Details')} /> </View> ); } } class SettingsScreen extends React.Component { static navigationOptions = { headerBackTitle:null, title:'SettingsScreen' }; render() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> {/* other code from before here */} <Button title="Go to Details" onPress={() => this.props.navigation.navigate('Details')} /> </View> ); } } const HomeStack = createStackNavigator( { Home: HomeScreen, Details: DetailsScreen, Four:FourScreen, Five:FiveScreen }, { defaultNavigationOptions:{ headerStyle:{ backgroundColor:'#fdd000', }, headerTintColor:'#fff', headerTitleColor:{ fontWeight:'bold' } } } ); const SettingsStack = createStackNavigator( { Settings:{ screen:SettingsScreen, } , Details: DetailsScreen, }, { defaultNavigationOptions:{ headerStyle:{ backgroundColor:'#fdd000', }, headerTintColor:'#fff', headerTitleColor:{ fontWeight:'bold' } } } ); HomeStack.navigationOptions = ({ navigation }) => { let tabBarVisible = true; if (navigation.state.index > 0) { tabBarVisible = false; } return { tabBarVisible, }; }; SettingsStack.navigationOptions = ({ navigation }) => { let tabBarVisible = true; if (navigation.state.index > 0) { tabBarVisible = false; } return { tabBarVisible, }; }; export default createAppContainer(createBottomTabNavigator( { Home: { screen:HomeStack, navigationOptions: { tabBarLabel: '首页', // tabBar显示的文字 tabBarIcon: ({tintColor}) => ( // tabBar显示的图标 // 这里使用了react-native-vector-icons, 不熟悉的请看上方链接 <Ionicons name={'ios-add'} size={30} color={tintColor} /> ) } }, Settings: { screen:SettingsStack, navigationOptions: { tabBarLabel: '设置', // tabBar显示的文字 tabBarIcon: ({tintColor}) => ( // tabBar显示的图标 // 这里使用了react-native-vector-icons, 不熟悉的请看上方链接 <Ionicons name={'ios-close'} size={30} color={tintColor} /> ) } }, }, { tabBarOptions: { activeTintColor: '#fdd000', } } )); const styles = StyleSheet.create({ tabBarIconStyle: { width: 30, height: 30, }, });