Facebook力推导航库:React Navigation使用详解
本文來自Songlcy投稿:文章地址:http://blog.csdn.net/u013718120/article/details/72357698
一、開源庫介紹
今年1月份,新開源的react-natvigation庫備受矚目。在短短不到3個月的時間,github上星數已達4000+。Fb推薦使用庫,并且在React Native當前最新版本0.44中將Navigator刪除。react-navigation據稱有原生般的性能體驗效果。可能會成為未來React Native導航組件的主流軍。本篇內容基于【 ^1.0.0-beta.9 】版本來介紹關于該庫的使用和實戰技巧??梢钥吹?#xff0c;雖然是beta版本,不過基本穩定,大家可放心在項目中使用。該庫包含三類組件:
剛創建的React Native交流10群:157867561,歡迎各位大牛,React Native技術愛好者加入交流!同時博客右側歡迎微信掃描關注訂閱號,移動技術干貨,精彩文章技術推送!
(1)StackNavigator:用來跳轉頁面和傳遞參數
(2)TabNavigator:類似底部導航欄,用來在同一屏幕下切換不同界面
(3)DrawerNavigator:側滑菜單導航欄,用于輕松設置帶抽屜導航的屏幕
二、React-Navigation使用
具體內容大致分為如下:
(1)react-navigation庫屬性介紹
(2)StackNavigator、TabNavigator實現界面間跳轉,Tab切換
(3)StackNavigator界面間跳轉、傳值、取值
(4)DrawerNavigator實現抽屜導航菜單
(5)DrawerNavigator擴展功能
(6)修改源碼,定制UI界面
2.1、StackNavigator屬性介紹
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | navigationOptions:配置StackNavigator的一些屬性。? ????title:標題,如果設置了這個導航欄和標簽欄的title就會變成一樣的,不推薦使用? ????header:可以設置一些導航的屬性,如果隱藏頂部導航欄只要將這個屬性設置為null? ????headerTitle:設置導航欄標題,推薦? ????headerBackTitle:設置跳轉頁面左側返回箭頭后面的文字,默認是上一個頁面的標題??梢宰远x,也可以設置為null? ????headerTruncatedBackTitle:設置當上個頁面標題不符合返回箭頭后的文字時,默認改成"返回"? ????headerRight:設置導航條右側。可以是按鈕或者其他視圖控件? ????headerLeft:設置導航條左側。可以是按鈕或者其他視圖控件? ????headerStyle:設置導航條的樣式。背景色,寬高等? ????headerTitleStyle:設置導航欄文字樣式? ????headerBackTitleStyle:設置導航欄‘返回’文字樣式? ????headerTintColor:設置導航欄顏色? ????headerPressColorAndroid:安卓獨有的設置顏色紋理,需要安卓版本大于5.0? ????gesturesEnabled:是否支持滑動返回手勢,iOS默認支持,安卓默認關閉? screen:對應界面名稱,需要填入import之后的頁面? mode:定義跳轉風格? ???card:使用iOS和安卓默認的風格? ???modal:iOS獨有的使屏幕從底部畫出。類似iOS的present效果? headerMode:返回上級頁面時動畫效果? ???float:iOS默認的效果? ???screen:滑動過程中,整個頁面都會返回? ???none:無動畫? cardStyle:自定義設置跳轉效果? ???transitionConfig: 自定義設置滑動返回的配置? ???onTransitionStart:當轉換動畫即將開始時被調用的功能? ???onTransitionEnd:當轉換動畫完成,將被調用的功能? path:路由中設置的路徑的覆蓋映射配置? initialRouteName:設置默認的頁面組件,必須是上面已注冊的頁面組件? initialRouteParams:初始路由參數 |
注:大家可能對于path不太理解。path屬性適用于其他app或瀏覽器使用url打開本app并進入指定頁面。path屬性用于聲明一個界面路徑,例如:【/pages/Home】。此時我們可以在手機瀏覽器中輸入:app名稱://pages/Home來啟動該App,并進入Home界面。
2.2、TabNavigator屬性介紹
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | screen:和導航的功能是一樣的,對應界面名稱,可以在其他頁面通過這個screen傳值和跳轉。? navigationOptions:配置TabNavigator的一些屬性? title:標題,會同時設置導航條和標簽欄的title? tabBarVisible:是否隱藏標簽欄。默認不隱藏(true)? tabBarIcon:設置標簽欄的圖標。需要給每個都設置? tabBarLabel:設置標簽欄的title。推薦? 導航欄配置? tabBarPosition:設置tabbar的位置,iOS默認在底部,安卓默認在頂部。(屬性值:'top','bottom')? swipeEnabled:是否允許在標簽之間進行滑動? animationEnabled:是否在更改標簽時顯示動畫? lazy:是否根據需要懶惰呈現標簽,而不是提前,意思是在app打開的時候將底部標簽欄全部加載,默認false,推薦為true? trueinitialRouteName: 設置默認的頁面組件? backBehavior:按 back 鍵是否跳轉到第一個Tab(首頁), none 為不跳轉? tabBarOptions:配置標簽欄的一些屬性iOS屬性? activeTintColor:label和icon的前景色 活躍狀態下? activeBackgroundColor:label和icon的背景色 活躍狀態下? inactiveTintColor:label和icon的前景色 不活躍狀態下? inactiveBackgroundColor: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:圖標樣式 |
2.3、DrawerNavigator屬性介紹
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | DrawerNavigatorConfig? ????drawerWidth - 抽屜的寬度? ????drawerPosition - 選項是左或右。 默認為左側位置? ????contentComponent - 用于呈現抽屜內容的組件,例如導航項。 接收抽屜的導航。 默認為DrawerItems? ????contentOptions - 配置抽屜內容? ????initialRouteName - 初始路由的routeName? ????order - 定義抽屜項目順序的routeNames數組。? ????路徑 - 提供routeName到路徑配置的映射,它覆蓋routeConfigs中設置的路徑。? ????backBehavior - 后退按鈕是否會切換到初始路由? 如果是,設置為initialRoute,否則為none。 默認為initialRoute行為? ???DrawerItems的contentOptions屬性? ????activeTintColor - 活動標簽的標簽和圖標顏色? ????activeBackgroundColor - 活動標簽的背景顏色? ????inactiveTintColor - 非活動標簽的標簽和圖標顏色? ????inactiveBackgroundColor - 非活動標簽的背景顏色? ????內容部分的樣式樣式對象? ????labelStyle - 當您的標簽是字符串時,要覆蓋內容部分中的文本樣式的樣式對象 |
從上述中大致了解了react-navigation三種組件的一些基本屬性,所以到我們甩起袖子擼代碼見證下奇跡了。
2.4、使用StackNavigator + TabNavigator實現Tab界面切換、界面間導航
API定義:StackNavigator(RouteConfigs, StackNavigatorConfig)、TabNavigator(RouteConfigs, TabNavigatorConfig)
(1)集成 react-navigation:在終端執行 【 npm install react-navigation --save 】
(2)界面中導入必要組件:
?| 1 2 3 | import {StackNavigator,TabNavigator,TabBarBottom} from 'react-navigation';? import HomeScreen from './pages/HomePage';? import MineScreen from './pages/MinePage'; |
(3)定義TabNavigator:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | const Tab = TabNavigator(? ??{? ????Home:{? ??????screen:HomeScreen,? ??????navigationOptions:({navigation}) => ({? ????????tabBarLabel:'首頁',? ????????tabBarIcon:({focused,tintColor}) => (? ??????????<TabBarItem? ????????????tintColor={tintColor}? ????????????focused={focused}? ????????????normalImage={require('./imgs/nav_fav@2x.png')}? ????????????selectedImage={require('./imgs/nav_fav_actived@3x.png')}? ??????????/>? ????????)? ??????}),? ????},? ????Mine:{? ??????????screen:MineScreen,? ??????????navigationOptions:({navigation}) => ({? ??????????tabBarLabel:'我',? ??????????tabBarIcon:({focused,tintColor}) => (? ????????????<TabBarItem? ?????????????tintColor={tintColor}? ??????????????focused={focused}? ??????????????normalImage={require('./imgs/tab_me_nor@3x.png')}? ??????????????selectedImage={require('./imgs/tab_me_selected@2x.png')}? ????????????/>? ??????????)? ????????}),? ??????},? ????},? ????{? ??????tabBarComponent:TabBarBottom,? ??????tabBarPosition:'bottom',? ??????swipeEnabled:false,? ??????animationEnabled:false,? ??????lazy:true,? ??????tabBarOptions:{? ????????activeTintColor:'#06c1ae',? ????????inactiveTintColor:'#979797',? ????????style:{backgroundColor:'#ffffff',},? ????????labelStyle: {? ??????????????fontSize: 20, // 文字大小? ??????????},? ??????}? ????}? ??); |
TabBarItem為封裝的組件:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 } }? ????????????/>? ????????)? ????}? } |
可以看到,我們定義了一個名稱為【Tab】的TabNavigator的導航組件。在組件中,分為兩層參數:
(1)第一層參數定義了要切換的界面,即【首頁】、【我】兩個界面組件,通過screen屬性指定。并且通過navigationOptions屬性設置相關屬性參數。
(2)設置導航欄的屬性參數。
TabNavigator定義好之后,需要用StackNavigator,顧名思義,StackNavigator就是以棧的方式來存放整個界面的,而TabNavigator是作為一個界面內不同子界面之間切換。所以還需要我們定義StackNavigator:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const Navigator = StackNavigator(? ??{? ????Tab:{screen:Tab},? ????Product:{screen:ProductScreen}? ??},? ??{? ????navigationOptions:{? ??????headerBackTitle:null,? ??????headerTintColor:'#333333',? ??????showIcon:true,? ?????swipeEnabled:false,? ?????animationEnabled:false,? ????},? ????mode:'card',? ??}); |
看起來和TabNavigator很相似,同樣是指定了兩個參數:
(1)指定要跳轉的界面組件。同樣是screen屬性標識界面組件,不多贅述。
(2)定義跳轉屬性參數,即頂部導航欄的一些參數設置和跳轉方式。
可以看到,我們將Tab作為一個界面設置到了StackNavigator。這樣就可以實現Tab導航和界面間跳轉的效果了。
最后就是在render中引用StackNavigator:
?| 1 2 3 4 5 6 7 8 | export default class Demo extends Component {? ??render() {? ????????return (? ??????????<Navigator />? ????????);? ??}? } |
StackNavigator還提供了onNavigationStateChange回調方法,用來監聽導航狀態的改變。具體不再贅述。實現了界面跳轉和切換,那么就該來增加下界面之間的感情了,來看看如何實現界面之間的傳值和取值。
2.5、界面間跳轉、傳值、取值
在界面組件注入到StackNavigator中時,界面組件就被賦予了navigation屬性,即在界面組件中可以通過【this.props.navigation】獲取并進行一些操作。
navigation屬性中提供了很多的函數簡化界面間操作,簡單列舉幾點:
(1)通過navigate函數實現界面之間跳轉:
?| 1 | this.props.navigation.navigate('Mine'); |
參數為我們在StackNavigator注冊界面組件時的名稱。同樣也可以從當前頁面返回到上一頁:
?| 1 2 | // 返回上一頁? this.props.navigation.goBack(); |
(2)跳轉時傳值:
?| 1 | this.props.navigation.navigate('Mine',{info:'傳值過去'}); |
第一個參數同樣為要跳轉的界面組件名稱,第二個參數為要傳遞的參數,info可以理解為key,后面即傳遞的參數。
(3)獲取值:
?| 1 | {this.props.navigation.state.params.info} |
通過state.params來獲取傳來的參數,后面為key值。此處為info。
以上實現完成,我們就可以愉快的玩耍啦~~ 什么?忽然發現在Android上的效果和IOS效果不一樣。老板要界面一致哇~ 怎么辦?那就需要我們進行簡單的適配了。
三、DrawerNavigator實現抽屜導航
1、導航實現
API定義:DrawerNavigator(RouteConfigs,DrawerNavigatorConfig)
(1)界面中定義DrawerNavigator:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import {StackNavigator,TabNavigator,DrawerNavigator} from 'react-navigation';? import HomeScreen from './pages/HomePage';? import MineScreen from './pages/MinePage';? export default class Demo extends Component {? ??render() {? ????????return (? ??????????<Navigator />? ????????);? ??}? }? const Navigator = DrawerNavigator({? ????Home:{screen:HomeScreen},? ????Mine:{screen:MineScreen},? });? const styles = StyleSheet.create({? ????container: {? ????????flex: 1,? ????},? });? AppRegistry.registerComponent('Demo', () => Demo); |
定義方式和StackNavigator基本類似,不再贅述。
(2)HomeScreen界面和MineScreen界面:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | export default class HomePage extends Component {? ????static navigationOptions = {? ????????drawerLabel: '首頁',? ????????drawerIcon:({tintColor}) => (? ????????????<Image? ????????????????source={require('./../imgs/ic_happy.png')}? ????????????????style={[styles.icon, {tintColor: tintColor}]}/>? ????????),? ????};? ????render() {? ????????return(? ????????????<View style={{flex:1}}>? ????????????????<Text onPress={this._skip.bind(this)}>點擊跳轉</Text>? ????????????</View>? ????????);? ????}? ????_skip() {? ????????this.props.navigation.navigate("Mine");? ????}? }? export default class MinePage extends Component {? ????static navigationOptions = {? ????????drawerLabel:'我',? ?????????drawerIcon: ({ tintColor }) => (? ????????????<Image? ????????????????source={require('./../imgs/ic_h.png')}? ????????????????style={[styles.icon, {tintColor: tintColor}]}? ????????????/>? ????????),? ????};? ????render() {? ????????return(? ????????????<View style={{flex:1}}>? ????????????????<Text onPress={this._skip.bind(this)}>返回上一界面</Text>? ????????????</View>? ????????);? ????}? ????/**? ?????* 跳轉? ?????*/? ????_skip() {? ????????this.props.navigation.goBack();? ????}? } |
代碼很簡單,實現了界面之間的跳轉。
2、擴展功能
(1)默認DrawerView不可滾動。要實現可滾動視圖,必須使用contentComponent自定義容器,如下所示:
?| 1 2 3 4 5 | {? ??drawerWidth:200,? ??抽屜位置:“對”? ??contentComponent:props => <ScrollView> <DrawerItems {... props} /> </ ScrollView>? } |
(2)可以覆蓋導航使用的默認組件,使用DrawerItems自定義導航組件:
?| 1 2 3 4 5 6 7 | import {DrawerItems} from 'react-navigation';? const CustomDrawerContentComponent = (props) => (? ??<View style = {style.container}>? ????<DrawerItems {... props} />? ??</View>??? ); |
(3)嵌套抽屜導航
如果您嵌套DrawerNavigation,抽屜將顯示在父導航下方。
四、react-navigation源碼定制
(1)適配頂部導航欄標題:
測試中發現,在iphone上標題欄的標題為居中狀態,而在Android上則是居左對齊。所以需要我們修改源碼,進行適配。
【node_modules -- react-navigation -- src -- views -- Header.js】的326行代碼處,修改為如下:
?| 1 2 3 4 5 6 7 8 | title: {? ???bottom: 0,? ???left: TITLE_OFFSET,? ???right: TITLE_OFFSET,? ???top: 0,? ???position: 'absolute',? ???alignItems: 'center',? ?} |
(2)去除返回鍵文字顯示:
【node_modules -- react-navigation -- src -- views -- HeaderBackButton.js】的91行代碼處,修改為如下即可。
?| 1 2 3 4 5 6 7 8 9 | {Platform.OS === 'ios' &&? ?????title &&? ?????<Text? ???????onLayout={this._onTextLayout}? ???????style={[styles.title, { color: tintColor }]}? ???????numberOfLines={1}? ?????>? ???????{backButtonTitle}? ?????</Text>} |
將上述代碼刪除即可。
(3)設置標題欄的按鈕單擊事件:
因為在界面組件中設置標題參數時,需要將navigationOptions定義成static。所以我們不能直接通過this.xxx.bind(this)來調用自定義函數,怎么辦呢?可以通過如何方式解決:
?| 1 2 3 4 5 6 7 8 9 10 11 12 | class demo extends Component {? ????static navigationOptions =({navigation})=>({? ????????????right:( <Button? onPress={state.params.clickParams}/>)? ????})? ????_btnClick=()=> {? ?????alert('單擊')? ????};? ????componentWillMount() {? ???????this.props.navigation.setParams({clickParams:this._btnClick})? ????}? } |
(4)動態設置標題欄顯示和隱藏
根據(3)中的思想,我們可以利用setParams來動態修改狀態欄的顯示和隱藏:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 | class demo extends Component {? ????static navigationOptions = ({navigation}) =>({? ???????????visible: state.params.headerState ,? ????});? ????render(){? ????????return(? ????????????<Button? ????????????title="Hide Header"? ????????????onPress={() => this.props.navigation.setParams({ headerState : 'none' })}? ????????/>)? ????}? } |
五、效果圖
抽屜導航:
以上就是我們實戰中常用的屬性和技巧。具體的操作還需要大家在實踐過程中測試體會。
剛創建的React Native交流10群:157867561,歡迎各位大牛,React Native技術愛好者加入交流!同時博客右側歡迎微信掃描關注訂閱號,移動技術干貨,精彩文章技術推送!
尊重原創,轉載請注明:From Sky丶清(http://www.lcode.org) 侵權必究!
引用原文:http://www.lcode.org/facebook-react-navigation/
?
寫博客是為了記住自己容易忘記的東西,另外也是對自己工作的總結,文章可以轉載,無需版權。希望盡自己的努力,做到更好,大家一起努力進步!
如果有什么問題,歡迎大家一起探討,代碼如有問題,歡迎各位大神指正!
轉載于:https://www.cnblogs.com/summary-2017/p/8626384.html
總結
以上是生活随笔為你收集整理的Facebook力推导航库:React Navigation使用详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FineBI学习系列之FineBI的Wi
- 下一篇: gson