參考資料: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, }, });