React Native導航器之react-navigation使用


在上一節Navigation組件,我們使用系統提供的導航組件做了一個跳轉的例子,不過其實戰能力不強,這里推薦一個超牛逼的第三方庫:react-navigation。在講react-navigation之前,我們先看一下常用的導航組件。

導航控件

常見的導航主要分為三種: 
1.StackNavigator :類似於普通的Navigator,屏幕上方導航欄 
2.TabNavigator:obviously, 相當於iOS里面的TabBarController,屏幕下方標簽欄 
3.DrawerNavigator:抽屜效果,左側滑出這種效果。

在你使用navigation的每一個界面navigation都提供相關的屬性和響應方法,常見的有: 
navigate 定義跳轉到另一個頁面 
調用此方法去鏈接你的其他界面,主要有以下參數: 
·routeName- 目標路由名稱,將在你的app router中注冊 
·params-將參數合並到目標router中 
·action-(高級)sub-action ,如果該界面是一個navigator的話,將運行這個sub-action

例如:

class HomeScreen extends React.Component { render() { const {navigate} = this.props.navigation; return ( <View> <Text>This is the home screen of the app</Text> <Button onPress={() => navigate('Profile', {name: 'Brent'})} title="點擊我跳轉" /> </View> ) } }

 

state當前路由狀態

每個界面通過this.props.navigation.state去訪問它的router,state其中包括了: 
·routeName - router配置的名稱 
·key-用來區分router的唯一標示 
·params-可選的一些string參數 
setParams-更改router中的參數 
該方法允許界面更改router中的參數,可以用來動態的更改header的內容 
goBack-返回,pop回上一級 
dispatch -使用dispatch可以向任何navigation傳遞一些其他的action,主要支持的action有

例如:

import { NavigationActions } from 'react-navigation' const navigationAction = NavigationActions.navigate({ routeName: 'Profile', params: {}, // navigate can have a nested navigate action that will be run inside the child router action: NavigationActions.navigate({ routeName: 'SubProfileRoute'}) }) this.props.navigation.dispatch(navigationAction)

Reset

Reset方法會擦除掉所有的導航狀態,並且使用新的結果替代。

import { NavigationActions } from 'react-navigation' const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'Profile'}) ] }) this.props.navigation.dispatch(resetAction)

SetParams

為指定的router更新參數,該參數必須是已經存在於router的param中。

import { NavigationActions } from 'react-navigation' const setParamsAction = NavigationActions.setParams({ params: {}, // these are the new params that will be merged into the existing route params // The key of the route that should get the new params key: 'screen-123', }) this.props.navigation.dispatch(setParamsAction)

StackNavigator使用

StackNavigator使用比較簡單,看一個常見的例子:

class MyHomeScreen extends React.Component { static navigationOptions = { title: 'Home', //設置navigator的title } render() { return ( //button的onPress方法,實現點擊跳轉界面,並且傳遞參數name:Lucy <Button onPress={() => this.props.navigation.navigate('Profile', {name: 'Lucy'})} title="Go to Lucy's profile" /> ); } } //生成路由關系 const ModalStack = StackNavigator({ Home: { //對應界面MyHomeScreen screen: MyHomeScreen, }, Profile: { path: 'people/:name', screen: MyProfileScreen, }, });

StackNavigatorConfig

option for the route(路由選項):

·initialRouteName -為stack設置默認的界面,必須和route configs里面的一個key匹配。 
·initialRouteParams - 初始路由的參數。 
·navigationOptions- 屏幕導航的默認選項。 
·paths-route config里面路徑設置的映射。

Visual Option(視覺選項):

·mode- 定義渲染(rendering)和轉換(transitions)的模式,兩種選項: 
1) card-使用標准的iOS和Android的界面切換,這是默認的。 
2)modal- 僅在iOS端有用,即模態出該視圖。

·headerMode- 指定header應該如何被渲染,選項: 
1)float- 共用一個header 意思就是有title文字漸變效果。 
2)screen- 各用各的header 意思就是沒有title文字漸變效果。 
3)none- 沒有header。

·cardStyle- 使用該屬性繼承或者重載一個在stack中的card的樣式。 
·onTransitionStart- 一個函數,在換場動畫開始的時候被激活。 
·onTransitionEnd- 一個函數,在換場動畫結束的時候被激活。

你還可以定義一個靜態的navigationOptions在你的組件之上。

lass ProfileScreen extends React.Component {
  //設置navigation選項 static navigationOptions = { //標題 title: ({ state }) => `${state.params.name}'s Profile!`, //頭部定義了一個右按鈕,來改變edit的狀態 ing或者完成 header: ({ state, setParams }) => ({ // Render a button on the right side of the header // When pressed switches the screen to edit mode. right: ( <Button title={state.params.editing ? 'Done' : 'Edit'} onPress={() => setParams({editing: state.params.editing ? false : true})} /> ), }), }; ...

常用的配置中,主要有以下參數需要注意: 
1)visible - bool值,header是否可見。 
2)title-標題 String或者是一個react 節點 
3)backTitle-返回按鈕在iOS平台上,默認是title的值 
4)right- react 節點顯示在header右邊,例如右按鈕 
5)left- react 節點顯示在header左邊,例如左按鈕 
6)style-header的style 
7)titleStyle- header的title的style (^__^) 嘻嘻…… 
8)tintColor- header的前景色 
·cardStack- 配置card stack

react-navigation

說完常見的導航器,我們在看看本文的重點:react-navigation的使用。 
首先看一下效果: 
這里寫圖片描述

1,在項目目錄下,安裝React-navigation庫

npm install --save react-navigation 

2,使用StactkNavigator來管理堆棧。暫且命名為HomeScreen.js。默認入口頁面代碼如下:

import React from 'react'; import { AppRegistry, Text, } from 'react-native'; //導入stack導航組件 import { StackNavigator } from 'react-navigation'; class HomeScreen extends React.Component { static navigationOptions = { title: 'Welcome',//標題 }; render() { return <Text>Hello, Navigation!</Text>; } } //導航注冊 const SimpleApp = StackNavigator({ Home: { screen: HomeScreen }, }); AppRegistry.registerComponent('SimpleApp', () => SimpleApp);

運行效果: 
這里寫圖片描述

3,添加一個新的頁面

 class ChatScreen extends React.Component { static navigationOptions = { title: 'Chat with Lucy', }; render() { return ( <View> <Text>Chat with Lucy</Text> </View> ); } }

 

4,在HomeScreen中添加一個button組件,使用routeName Chat關聯到ChatScreen。

 class HomeScreen extends React.Component { static navigationOptions = { title: 'Welcome', }; render() { const { navigate } = this.props.navigation; return ( <View> <Text>Hello, Chat App!</Text> <Button onPress={() => navigate('Chat')} title="Chat with Lucy" /> </View> ); } }

 

這段代碼主要是給Button綁定onPress事件。這時候,我們使用的兩個跳轉的頁面需要在StackNavigator進行注冊:

 const SimpleApp = StackNavigator({ Home: { screen: HomeScreen }, Chat: { screen: ChatScreen },//新添加的頁面 });

所以完整的代碼是:

class HomeScreen extends React.Component { static navigationOptions = { title: 'Welcome',//設置標題內容 }; render() { const { navigate } = this.props.navigation; return ( <View> <Text>Hello, Navigation!</Text> <Button onPress={() => navigate('Chat',{user:'Lucy'})} title="Chat with Lucy"/> </View> ); } } const SimpleApp = StackNavigator({ Home: {screen: HomeScreen}, Chat:{screen:ChatScreen}, }); 

參數傳遞

在頁面的跳轉過程中,往往會伴隨着參數的傳遞。

1,在第一個頁面定義參數,將參數傳值給需要傳值的頁面

constructor(props) { super(props); this.state = {}; } ... if(navigator) { navigator.push({ name: 'SecondPageComponent', component: SecondPageComponent, params:{ user:this.state.user, pwd:this.state.pwd } }) } 

 

2,如果需要監聽頁面的state狀態

onChangeText={(text) => this.setState({user: text})} 

3,另一個頁面接受參數

componentDidMount() {  
            //這里獲取從FirstPageComponent傳遞過來的參數: id  
            this.setState({ user:this.props.user, pwd:this.props.pwd }); } 

 

4,去的傳過來的值:

value={this.state.user } 

react-navigation參數傳遞

對於 react-navigation參數的傳遞,使用上比較簡單,只需要在navigate中加一個json格式的對象即可,如:

 navigate('Chat', { user: 'Lucy' })

然后在接收的頁面:

class ChatScreen extends React.Component { static navigationOptions = { // Nav options can be defined as a function of the navigation prop: title: ({ state }) => `Chat with ${state.params.user}`, }; render() { // The screen's current route is passed in to `props.navigation.state`: const { params } = this.props.navigation.state; return ( <View> <Text>Chat with {params.user}</Text> </View> ); } }

 

所以,你就可以看到如下的效果: 
這里寫圖片描述

TabNavigator

TabNavigator類似於底部導航效果

// 注冊tabs const Tabs = TabNavigator({ Home: { screen: Home, navigationOptions: { // 也可以寫在組件的static navigationOptions內 tabBar: { label: '首頁', icon: ({tintColor}) => (<Image source={require('./app/images/home.png')} style={[{tintColor: tintColor},styles.icon]}/>), }, } }, Bill: { screen: Bill, navigationOptions: { tabBar: { label: '賬單', icon: ({tintColor}) => (<Image source={require('./app/images/bill.png')} style={[{tintColor: tintColor},styles.icon]}/>), }, } }, Me: { screen: Me, navigationOptions: { tabBar: { label: '我', icon: ({tintColor}) => (<Image source={require('./app/images/me.png')} style={[{tintColor: tintColor},styles.icon]}/>), }, } } }, { animationEnabled: false, // 切換頁面時是否有動畫效果 tabBarPosition: 'bottom', // 顯示在底端,android 默認是顯示在頁面頂端的 swipeEnabled: false, // 是否可以左右滑動切換tab backBehavior: 'none', // 按 back 鍵是否跳轉到第一個Tab(首頁), none 為不跳轉 tabBarOptions: { activeTintColor: '#ff8500', // 文字和圖片選中顏色 inactiveTintColor: '#999', // 文字和圖片未選中顏色 showIcon: true, // android 默認不顯示 icon, 需要設置為 true 才會顯示 indicatorStyle: { height: 0 // 如TabBar下面顯示有一條線,可以設高度為0后隱藏 }, style: { backgroundColor: '#fff', // TabBar 背景色 // height: 44 }, labelStyle: { fontSize: 10, // 文字大小 }, }, });

 

DrawerNavigator

DrawerNavigator類似於抽屜側滑效果。

const DrawerNav = DrawerNavigator({ Home: { screen: Home }, Bill: { screen: Bill }, Me: { screen: Me }, HomeTwo: { screen: HomeTwo }, HomeThree: { screen: HomeThree }, HomeFour: { screen: HomeFour }, BillTwo: { screen: BillTwo }, BillThree: { screen: BillThree } }, { drawerWidth: 200, // 抽屜寬 drawerPosition: 'left', // 抽屜在左邊還是右邊 // contentComponent: CustomDrawerContentComponent, // 自定義抽屜組件 contentOptions: { initialRouteName: Home, // 默認頁面組件 activeTintColor: 'white', // 選中文字顏色 activeBackgroundColor: '#ff8500', // 選中背景顏色 inactiveTintColor: '#666', // 未選中文字顏色 inactiveBackgroundColor: '#fff', // 未選中背景顏色 style: { // 樣式 } } });

iOS版設置

在iOS中使用react-navigation需要注意以下幾點: 
使用Xcode設置Schemes; 
在AppDelegate添加一下代碼:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; }

js組件在注冊路由時設置唯一的路徑path, 例如Home2: { screen: Home2, path:’app/Home2’ }; 
在手機瀏覽器訪問demo4://app/Home2, 彈窗選擇打開, 就可以打開demo4 app並進到Home2頁面。

react-native-tab-navigator

這里寫圖片描述

直接上代碼:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native * @flow */ import React, { Component } from 'react'; import TabNavigator from 'react-native-tab-navigator'; import { AppRegistry, StyleSheet, Text, Image, View } from 'react-native'; const TabNavigatorItem =TabNavigator.Item; //默認選項 const TAB_HOME_NORMAL=require('./image/tabbar_homepage.png'); const TAB_MINE_NORMAL=require('./image/tabbar_mine.png'); //選中 const TAB_HOME_PRESS=require('./image/tabbar_homepage_selected.png'); const TAB_MINE_PRESS=require('./image/tabbar_mine_selected.png'); export default class HelloWord extends Component { //默認選中 constructor(){ super(); this.state={ selectedTab:'Home', } } //點擊方法 onPress(tabName){ if(tabName){ this.setState({ selectedTab:tabName, } ); } } //渲染選項 renderTabView(title,tabName,tabContent,isBadge){ var tabNomal; var tabPress; switch (tabName) { case 'Home': tabNomal=TAB_HOME_NORMAL; tabPress=TAB_HOME_PRESS; break; case 'Mine': tabNomal=TAB_MINE_NORMAL; tabPress=TAB_MINE_PRESS; break; default: } return( <TabNavigatorItem selected={this.state.selectedTab===tabName} title={title} titleStyle={styles.tabText} selectedTitleStyle={styles.selectedTabText} renderIcon={()=><Image style={styles.icon} source={tabNomal}/>} renderSelectedIcon={()=><Image style={styles.icon} source={tabPress}/>} onPress={()=>this.onPress(tabName)} renderBadge={()=>isBadge?<View style={styles.badgeView}><Text style={styles.badgeText}>15</Text></View>:null} > <View style={styles.page}><Text>{tabContent}</Text></View> </TabNavigatorItem> ); } //自定義TabView tabBarView(){ return ( <TabNavigator tabBarStyle={styles.tab} > {this.renderTabView('首頁','Home','首頁模塊',true)} {this.renderTabView('我的','Mine','我的模塊',false)} </TabNavigator> ); } //渲染界面 render() { var tabView=this.tabBarView(); return ( <View style={styles.container}> {tabView} </View> ); } } const styles = StyleSheet.create({ container: { flex: 1 }, tabText: { fontSize: 10, color: 'black' }, selectedTabText: { fontSize: 10, color: 'green' }, tab:{ height: 52, alignItems:'center', backgroundColor:'#f4f5f6', }, tabIcon:{ width:25, height:25, }, badgeView:{ width:22, height:14 , backgroundColor:'#f85959', borderWidth:1, marginLeft:10, marginTop:3, borderColor:'#FFF', alignItems:'center', justifyContent:'center', borderRadius:8, }, badgeText:{ color:'#fff', fontSize:8, }, icon: { width: 22, height: 22 }, page: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFFFFF' }, }); AppRegistry.registerComponent('HelloWord', () => HelloWord); 

 

參考:React Native頁面參數傳遞 
https://reactnavigation.org/docs/intro/

react-native-tab-navigator封裝

 

引用原文:http://blog.csdn.net/xiangzhihong8/article/details/71249167?ref=myread

 

寫博客是為了記住自己容易忘記的東西,另外也是對自己工作的總結,文章可以轉載,無需版權。希望盡自己的努力,做到更好,大家一起努力進步!

如果有什么問題,歡迎大家一起探討,代碼如有問題,歡迎各位大神指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM