Facebook力推导航库:React Navigation使用详解
本文來自Songlcy投稿:文章地址:http://blog.csdn.net/u013718120/article/details/72357698
一、開源庫介紹
今年1月份,新開源的react-natvigation庫備受矚目。在短短不到3個月的時間,github上星數(shù)已達(dá)4000+。Fb推薦使用庫,并且在React Native當(dāng)前最新版本0.44中將Navigator刪除。react-navigation據(jù)稱有原生般的性能體驗效果。可能會成為未來React Native導(dǎo)航組件的主流軍。本篇內(nèi)容基于【 ^1.0.0-beta.9 】版本來介紹關(guān)于該庫的使用和實戰(zhàn)技巧。可以看到,雖然是beta版本,不過基本穩(wěn)定,大家可放心在項目中使用。該庫包含三類組件:
剛創(chuàng)建的React Native交流10群:157867561,歡迎各位大牛,React Native技術(shù)愛好者加入交流!同時博客右側(cè)歡迎微信掃描關(guān)注訂閱號,移動技術(shù)干貨,精彩文章技術(shù)推送!
(1)StackNavigator:用來跳轉(zhuǎn)頁面和傳遞參數(shù)
(2)TabNavigator:類似底部導(dǎo)航欄,用來在同一屏幕下切換不同界面
(3)DrawerNavigator:側(cè)滑菜單導(dǎo)航欄,用于輕松設(shè)置帶抽屜導(dǎo)航的屏幕
二、React-Navigation使用
具體內(nèi)容大致分為如下:
(1)react-navigation庫屬性介紹
(2)StackNavigator、TabNavigator實現(xiàn)界面間跳轉(zhuǎn),Tab切換
(3)StackNavigator界面間跳轉(zhuǎn)、傳值、取值
(4)DrawerNavigator實現(xiàn)抽屜導(dǎo)航菜單
(5)DrawerNavigator擴(kuò)展功能
(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:標(biāo)題,如果設(shè)置了這個導(dǎo)航欄和標(biāo)簽欄的title就會變成一樣的,不推薦使用? ????header:可以設(shè)置一些導(dǎo)航的屬性,如果隱藏頂部導(dǎo)航欄只要將這個屬性設(shè)置為null? ????headerTitle:設(shè)置導(dǎo)航欄標(biāo)題,推薦? ????headerBackTitle:設(shè)置跳轉(zhuǎn)頁面左側(cè)返回箭頭后面的文字,默認(rèn)是上一個頁面的標(biāo)題。可以自定義,也可以設(shè)置為null? ????headerTruncatedBackTitle:設(shè)置當(dāng)上個頁面標(biāo)題不符合返回箭頭后的文字時,默認(rèn)改成"返回"? ????headerRight:設(shè)置導(dǎo)航條右側(cè)。可以是按鈕或者其他視圖控件? ????headerLeft:設(shè)置導(dǎo)航條左側(cè)。可以是按鈕或者其他視圖控件? ????headerStyle:設(shè)置導(dǎo)航條的樣式。背景色,寬高等? ????headerTitleStyle:設(shè)置導(dǎo)航欄文字樣式? ????headerBackTitleStyle:設(shè)置導(dǎo)航欄‘返回’文字樣式? ????headerTintColor:設(shè)置導(dǎo)航欄顏色? ????headerPressColorAndroid:安卓獨有的設(shè)置顏色紋理,需要安卓版本大于5.0? ????gesturesEnabled:是否支持滑動返回手勢,iOS默認(rèn)支持,安卓默認(rèn)關(guān)閉? screen:對應(yīng)界面名稱,需要填入import之后的頁面? mode:定義跳轉(zhuǎn)風(fēng)格? ???card:使用iOS和安卓默認(rèn)的風(fēng)格? ???modal:iOS獨有的使屏幕從底部畫出。類似iOS的present效果? headerMode:返回上級頁面時動畫效果? ???float:iOS默認(rèn)的效果? ???screen:滑動過程中,整個頁面都會返回? ???none:無動畫? cardStyle:自定義設(shè)置跳轉(zhuǎn)效果? ???transitionConfig: 自定義設(shè)置滑動返回的配置? ???onTransitionStart:當(dāng)轉(zhuǎn)換動畫即將開始時被調(diào)用的功能? ???onTransitionEnd:當(dāng)轉(zhuǎn)換動畫完成,將被調(diào)用的功能? path:路由中設(shè)置的路徑的覆蓋映射配置? initialRouteName:設(shè)置默認(rèn)的頁面組件,必須是上面已注冊的頁面組件? initialRouteParams:初始路由參數(shù) |
注:大家可能對于path不太理解。path屬性適用于其他app或瀏覽器使用url打開本app并進(jìn)入指定頁面。path屬性用于聲明一個界面路徑,例如:【/pages/Home】。此時我們可以在手機(jī)瀏覽器中輸入:app名稱://pages/Home來啟動該App,并進(jìn)入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:和導(dǎo)航的功能是一樣的,對應(yīng)界面名稱,可以在其他頁面通過這個screen傳值和跳轉(zhuǎn)。? navigationOptions:配置TabNavigator的一些屬性? title:標(biāo)題,會同時設(shè)置導(dǎo)航條和標(biāo)簽欄的title? tabBarVisible:是否隱藏標(biāo)簽欄。默認(rèn)不隱藏(true)? tabBarIcon:設(shè)置標(biāo)簽欄的圖標(biāo)。需要給每個都設(shè)置? tabBarLabel:設(shè)置標(biāo)簽欄的title。推薦? 導(dǎo)航欄配置? tabBarPosition:設(shè)置tabbar的位置,iOS默認(rèn)在底部,安卓默認(rèn)在頂部。(屬性值:'top','bottom')? swipeEnabled:是否允許在標(biāo)簽之間進(jìn)行滑動? animationEnabled:是否在更改標(biāo)簽時顯示動畫? lazy:是否根據(jù)需要懶惰呈現(xiàn)標(biāo)簽,而不是提前,意思是在app打開的時候?qū)⒌撞繕?biāo)簽欄全部加載,默認(rèn)false,推薦為true? trueinitialRouteName: 設(shè)置默認(rèn)的頁面組件? backBehavior:按 back 鍵是否跳轉(zhuǎn)到第一個Tab(首頁), none 為不跳轉(zhuǎn)? tabBarOptions:配置標(biāo)簽欄的一些屬性iOS屬性? activeTintColor:label和icon的前景色 活躍狀態(tài)下? activeBackgroundColor:label和icon的背景色 活躍狀態(tài)下? inactiveTintColor:label和icon的前景色 不活躍狀態(tài)下? inactiveBackgroundColor:label和icon的背景色 不活躍狀態(tài)下? showLabel:是否顯示label,默認(rèn)開啟 style:tabbar的樣式? labelStyle:label的樣式安卓屬性? activeTintColor:label和icon的前景色 活躍狀態(tài)下? inactiveTintColor:label和icon的前景色 不活躍狀態(tài)下? showIcon:是否顯示圖標(biāo),默認(rèn)關(guān)閉? showLabel:是否顯示label,默認(rèn)開啟 style:tabbar的樣式? labelStyle:label的樣式 upperCaseLabel:是否使標(biāo)簽大寫,默認(rèn)為true? pressColor:material漣漪效果的顏色(安卓版本需要大于5.0)? pressOpacity:按壓標(biāo)簽的透明度變化(安卓版本需要小于5.0)? scrollEnabled:是否啟用可滾動選項卡 tabStyle:tab的樣式? indicatorStyle:標(biāo)簽指示器的樣式對象(選項卡底部的行)。安卓底部會多出一條線,可以將height設(shè)置為0來暫時解決這個問題? labelStyle:label的樣式? iconStyle:圖標(biāo)樣式 |
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 - 選項是左或右。 默認(rèn)為左側(cè)位置? ????contentComponent - 用于呈現(xiàn)抽屜內(nèi)容的組件,例如導(dǎo)航項。 接收抽屜的導(dǎo)航。 默認(rèn)為DrawerItems? ????contentOptions - 配置抽屜內(nèi)容? ????initialRouteName - 初始路由的routeName? ????order - 定義抽屜項目順序的routeNames數(shù)組。? ????路徑 - 提供routeName到路徑配置的映射,它覆蓋routeConfigs中設(shè)置的路徑。? ????backBehavior - 后退按鈕是否會切換到初始路由? 如果是,設(shè)置為initialRoute,否則為none。 默認(rèn)為initialRoute行為? ???DrawerItems的contentOptions屬性? ????activeTintColor - 活動標(biāo)簽的標(biāo)簽和圖標(biāo)顏色? ????activeBackgroundColor - 活動標(biāo)簽的背景顏色? ????inactiveTintColor - 非活動標(biāo)簽的標(biāo)簽和圖標(biāo)顏色? ????inactiveBackgroundColor - 非活動標(biāo)簽的背景顏色? ????內(nèi)容部分的樣式樣式對象? ????labelStyle - 當(dāng)您的標(biāo)簽是字符串時,要覆蓋內(nèi)容部分中的文本樣式的樣式對象 |
從上述中大致了解了react-navigation三種組件的一些基本屬性,所以到我們甩起袖子擼代碼見證下奇跡了。
2.4、使用StackNavigator + TabNavigator實現(xiàn)Tab界面切換、界面間導(dǎo)航
API定義:StackNavigator(RouteConfigs, StackNavigatorConfig)、TabNavigator(RouteConfigs, TabNavigatorConfig)
(1)集成 react-navigation:在終端執(zhí)行 【 npm install react-navigation --save 】
(2)界面中導(dǎo)入必要組件:
?| 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的導(dǎo)航組件。在組件中,分為兩層參數(shù):
(1)第一層參數(shù)定義了要切換的界面,即【首頁】、【我】兩個界面組件,通過screen屬性指定。并且通過navigationOptions屬性設(shè)置相關(guān)屬性參數(shù)。
(2)設(shè)置導(dǎo)航欄的屬性參數(shù)。
TabNavigator定義好之后,需要用StackNavigator,顧名思義,StackNavigator就是以棧的方式來存放整個界面的,而TabNavigator是作為一個界面內(nèi)不同子界面之間切換。所以還需要我們定義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很相似,同樣是指定了兩個參數(shù):
(1)指定要跳轉(zhuǎn)的界面組件。同樣是screen屬性標(biāo)識界面組件,不多贅述。
(2)定義跳轉(zhuǎn)屬性參數(shù),即頂部導(dǎo)航欄的一些參數(shù)設(shè)置和跳轉(zhuǎn)方式。
可以看到,我們將Tab作為一個界面設(shè)置到了StackNavigator。這樣就可以實現(xiàn)Tab導(dǎo)航和界面間跳轉(zhuǎn)的效果了。
最后就是在render中引用StackNavigator:
?| 1 2 3 4 5 6 7 8 | export default class Demo extends Component {? ??render() {? ????????return (? ??????????<Navigator />? ????????);? ??}? } |
StackNavigator還提供了onNavigationStateChange回調(diào)方法,用來監(jiān)聽導(dǎo)航狀態(tài)的改變。具體不再贅述。實現(xiàn)了界面跳轉(zhuǎn)和切換,那么就該來增加下界面之間的感情了,來看看如何實現(xiàn)界面之間的傳值和取值。
2.5、界面間跳轉(zhuǎn)、傳值、取值
在界面組件注入到StackNavigator中時,界面組件就被賦予了navigation屬性,即在界面組件中可以通過【this.props.navigation】獲取并進(jìn)行一些操作。
navigation屬性中提供了很多的函數(shù)簡化界面間操作,簡單列舉幾點:
(1)通過navigate函數(shù)實現(xiàn)界面之間跳轉(zhuǎn):
?| 1 | this.props.navigation.navigate('Mine'); |
參數(shù)為我們在StackNavigator注冊界面組件時的名稱。同樣也可以從當(dāng)前頁面返回到上一頁:
?| 1 2 | // 返回上一頁? this.props.navigation.goBack(); |
(2)跳轉(zhuǎn)時傳值:
?| 1 | this.props.navigation.navigate('Mine',{info:'傳值過去'}); |
第一個參數(shù)同樣為要跳轉(zhuǎn)的界面組件名稱,第二個參數(shù)為要傳遞的參數(shù),info可以理解為key,后面即傳遞的參數(shù)。
(3)獲取值:
?| 1 | {this.props.navigation.state.params.info} |
通過state.params來獲取傳來的參數(shù),后面為key值。此處為info。
以上實現(xiàn)完成,我們就可以愉快的玩耍啦~~ 什么?忽然發(fā)現(xiàn)在Android上的效果和IOS效果不一樣。老板要界面一致哇~ 怎么辦?那就需要我們進(jìn)行簡單的適配了。
三、DrawerNavigator實現(xiàn)抽屜導(dǎo)航
1、導(dǎo)航實現(xiàn)
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)}>點擊跳轉(zhuǎn)</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>? ????????);? ????}? ????/**? ?????* 跳轉(zhuǎn)? ?????*/? ????_skip() {? ????????this.props.navigation.goBack();? ????}? } |
代碼很簡單,實現(xiàn)了界面之間的跳轉(zhuǎn)。
2、擴(kuò)展功能
(1)默認(rèn)DrawerView不可滾動。要實現(xiàn)可滾動視圖,必須使用contentComponent自定義容器,如下所示:
?| 1 2 3 4 5 | {? ??drawerWidth:200,? ??抽屜位置:“對”? ??contentComponent:props => <ScrollView> <DrawerItems {... props} /> </ ScrollView>? } |
(2)可以覆蓋導(dǎo)航使用的默認(rèn)組件,使用DrawerItems自定義導(dǎo)航組件:
?| 1 2 3 4 5 6 7 | import {DrawerItems} from 'react-navigation';? const CustomDrawerContentComponent = (props) => (? ??<View style = {style.container}>? ????<DrawerItems {... props} />? ??</View>??? ); |
(3)嵌套抽屜導(dǎo)航
如果您嵌套DrawerNavigation,抽屜將顯示在父導(dǎo)航下方。
四、react-navigation源碼定制
(1)適配頂部導(dǎo)航欄標(biāo)題:
測試中發(fā)現(xiàn),在iphone上標(biāo)題欄的標(biāo)題為居中狀態(tài),而在Android上則是居左對齊。所以需要我們修改源碼,進(jìn)行適配。
【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)設(shè)置標(biāo)題欄的按鈕單擊事件:
因為在界面組件中設(shè)置標(biāo)題參數(shù)時,需要將navigationOptions定義成static。所以我們不能直接通過this.xxx.bind(this)來調(diào)用自定義函數(shù),怎么辦呢?可以通過如何方式解決:
?| 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)動態(tài)設(shè)置標(biāo)題欄顯示和隱藏
根據(jù)(3)中的思想,我們可以利用setParams來動態(tài)修改狀態(tài)欄的顯示和隱藏:
?| 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' })}? ????????/>)? ????}? } |
五、效果圖
抽屜導(dǎo)航:
以上就是我們實戰(zhàn)中常用的屬性和技巧。具體的操作還需要大家在實踐過程中測試體會。
剛創(chuàng)建的React Native交流10群:157867561,歡迎各位大牛,React Native技術(shù)愛好者加入交流!同時博客右側(cè)歡迎微信掃描關(guān)注訂閱號,移動技術(shù)干貨,精彩文章技術(shù)推送!
尊重原創(chuàng),轉(zhuǎn)載請注明:From Sky丶清(http://www.lcode.org) 侵權(quán)必究!
引用原文:http://www.lcode.org/facebook-react-navigation/
?
寫博客是為了記住自己容易忘記的東西,另外也是對自己工作的總結(jié),文章可以轉(zhuǎn)載,無需版權(quán)。希望盡自己的努力,做到更好,大家一起努力進(jìn)步!
如果有什么問題,歡迎大家一起探討,代碼如有問題,歡迎各位大神指正!
轉(zhuǎn)載于:https://www.cnblogs.com/summary-2017/p/8626384.html
總結(jié)
以上是生活随笔為你收集整理的Facebook力推导航库:React Navigation使用详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FineBI学习系列之FineBI的Wi
- 下一篇: gson