在2017年1月,新開源的react-navigation庫備受矚目。它有類似于原生版性能的體驗效果,可能會成為未來RN導航組件中的主力軍。該庫包含三類組件:
(1)StackNavigator:用來跳轉頁面和傳遞參數。stack就是數據結構的堆棧技術,遵循后進先出的原理。
(2)TabNavigator:類似底部導航欄,用來在同一屏幕下切換不同界面
(3)DrawerNavigator:側滑菜單導航欄,用于輕松設置帶抽屜導航的屏幕
一、屬性介紹
1.1StackNavigator屬性
- navigationOptions:用于配置StackNavigator的一些屬性。
- title:標題,如果設置了該屬性,導航欄和標簽欄的title就會變成一樣。故不建議使用
- header:設置一些導航的屬性,若想要隱藏頂部導航欄則只需要把這個屬性設置為null
- headerTitle:設置導航欄標題
- headerBackTitle:設置跳轉頁面左側返回箭頭后面的文字,默認是上一個頁面的標題,當然也可以自定義設置設置成null
- headerTruncatedBackTitle:設置當上個頁面標題不符合返回箭頭后的文字時,默認改成"返回"
- headerRight:設置導航條右側。可以是按鈕或者是其他視圖控件
- headerLeft:設置導航條右側。可以是按鈕或者是其他視圖控件
- headerStyle:設置導航條的樣式,背景色及寬高等
- headerTitleStyle:設置導航欄文字樣式
- headerBackTitleStyle:設置導航欄"返回"的文字樣式
- headerTintColor:設置導航欄顏色
- headerPressColorAndroid:安裝獨有的設置顏色紋理。當然只有在安卓5.0以上才有效果
- gesturesEnabled:是否支持滑動返回手勢。iOS默認支持,安卓默認關閉
- screen:對應界面名稱,需要填入import之后的頁面
- mode:定義跳轉風格
- card:使用iOS和安卓默認的風格。直接切換
- modal:iOS獨有的使屏幕從底部拖出
- headerMode:返回上級頁面時的動畫效果
- float:iOS的默認效果
- screen:滑動過程中,整個頁面都會返回
- none:無動畫
- cardStyle:自定義設置跳轉效果
- transitionConfig:自定義設置滑動返回的配置
- onTransitionStart:當轉換動畫即將被調用的功能
- onTransitionEnd:當轉換動畫完成時被調用的功能
- path:路由中設置的路徑的覆蓋映射配置。path用于聲明一個界面路徑
- initialRouteName:設置默認的頁面組件,必須是已經注冊的頁面組件
- initailRouteParams:設置路由參數
1.2TabNavigator屬性
- screen:和導航的功能一樣,對應界面名稱,可以在氣頭頁面通過這個screen傳值和跳轉
- navigationOptions:配置TabNavigator的一些屬性
- title:標題,會同時設置導航條和標簽欄的title
- tabBarVisible:是否顯示標簽欄。默認是true不隱藏
- tabBarIcon:設置標簽欄的圖標。需要給每一項都設置
- tabBarLabel:設置標簽欄的title
以下屬性配合導航使用
tabBarPosition:設置tabBar的位置,屬性值為top和bottom。iOS默認在底部,安卓默認在頂部
swipeEnabled:是否允許在標簽之間進行滑動
animationEnabled:是否在更改標簽時顯示動畫
lazy:是否在app打開的時候將底部的標簽欄全部加載,默認為flase。推薦打開
trueInitialRouteName:設置默認的頁面組件
backBehavior:按back鍵是否跳轉到第一個tab,none為不跳轉
tabBarOptions:設置標簽欄
-
專屬iOS屬性
- activeTintColor:設置在活躍狀態下,label和icon的前景色
- activeBackgroundColor:label和icon的背景色
- inactiveTintColor:設置在不活躍狀態下,label和icon的前景色
- inactiveTintColor:設置在不活躍狀態下,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:圖標樣式
1.3DrawerNavigator屬性介紹
- DrawerNavigatorConfig屬性
- drawerWidth - 抽屜的寬度
- drawerPosition - 選項是左或右。 默認為左側位置
- contentComponent - 用于呈現抽屜內容的組件,例如導航項。 接收抽屜的導航。 默認為DrawerItems
- contentOptions - 配置抽屜內容
- initialRouteName - 初始路由的routeName
- order - 定義抽屜項目順序的routeNames數組。
路徑 - 提供routeName到路徑配置的映射,它覆蓋routeConfigs中設置的路徑。 - backBehavior - 后退按鈕是否會切換到初始路由? 如果是,設置為initialRoute,否則為none。 默認為initialRoute行為
- DrawerItems的contentOptions屬性
- activeTintColor - 活動標簽的標簽和圖標顏色
- activeBackgroundColor - 活動標簽的背景顏色
- inactiveTintColor - 非活動標簽的標簽和圖標顏色
- inactiveBackgroundColor - 非活動標簽的背景顏色
內容部分的樣式樣式對象 - labelStyle - 當您的標簽是字符串時,要覆蓋內容部分中的文本樣式的樣式對象
二、案例
2.1StackNavigation案例
- 集成第三方庫
使用npm安裝react-navigation庫,--save表示將該組件寫入到package.json文件中。
npm install react-navigation --save
當然,也可以采用yarn工具將該庫添加到項目中
yarn add react-navigation
-
導入組件到項目中
本項目創建于0.49.2的環境中,這次RN對該版本做了重大改進。安卓端和iOS的文件混合成為index.js文件。而文件App.js注冊到了又注冊到了index.js文件。故我們將需要用到的代碼編寫在App.js文件中。
import {StackNavigator} from 'react-navigation';
- 創建導航,并且添加路由
import HomeScreen from './HomeScreen'; //導入需要展示的頁面
const Navigator = StackNavigator(
//設置導航要展示的頁面
{
HomeScreen:{screen:HomeScreen}
},
//設置navigationOptions屬性對象
{
navigationOptions: {
title: '標題', //在導航中顯示的標題內容
headerBackTitle:null,
headerTintColor:'#333333',
showIcon:true,
swipeEnabled:false,
animationEnabled:false,
},
mode:'card', //設置mode屬性
}
);
- 在render函數中返回導航
export default class App extends Component<{}> {
render() {
return (
<Navigator/>
);
}
}
- HomeScreen.js代碼實現
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
AppRegistry,
Text,
View
} from 'react-native';
export default class HomeScreen extends Component {
render(){
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text>你好啊 在干嘛呢</Text>
</View>
);
}
}
下面可以來做導航的跳轉操作
為了實現跳轉操作的功能,需要先新建一個頁面,并且將這個頁面添加到導航中去。
- 導入頁面到App.js文件
import ChatScreen from './ChatScreen' //新建的文件
const Navigator = StackNavigator(
{
HomeScreen:{screen:HomeScreen},
ChatScreen:{screen:ChatScreen} //這是新添加的導航界面
- 跳轉操作
只要界面加入到了導航當中,組件中就會自動添加navigation的navigate屬性。使用該屬性可以跳轉到下一個界面。下面是HomeScreen中的代碼。ChatScreen是第二個導航界面。在HomeScreen中添加一個button組件,使用routeName路由名稱ChatScreen關聯到組件ChatScreen.
export default class HomeScreen extends Component {
render(){
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text>你好啊 在干嘛呢</Text>
<Button
onPress={()=>this.props.navigation.navigate('ChatScreen')}
title={"chat with lucy"}
/>
</View>
);
}
}
- 返回操作
當第二個界面想要回歸到上一個界面時,也要用到navigation的goBack屬性。當然導航有自身的返回按鈕。以下代碼是ChatScreen組件的代碼,當用戶組件Text也會返回到上一個界面。
export default class ChatScreen extends Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text onPress={()=>this.props.navigation.goBack()}>Chat with Lucy</Text>
</View>
);
}
}
- 傳遞參數
在ChatScreen頁面中,如果直接寫死標題則不利于代碼的可維護性。所以我們可以在導航的時候傳遞參數。首先編輯一下HomeScreen組件,傳遞自定義的屬性user參數到路由中去。
export default class HomeScreen extends Component {
render(){
const { navigate } = this.props.navigation;
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text>你好啊 在干嘛呢</Text>
<Button
onPress={()=>navigate('ChatScreen',{user:'dudu'})}
title={"chat with lucy"}
/>
</View>
);
}
}
之后可以編輯ChatScreen組件顯示的user參數,這個參數通過route來傳遞。為了代碼的健壯性,如果外界的user屬性有值,就將user賦值給title。如果沒有則讓title為空。
設置導航右邊的菜單,設置一個“返回”的文字
static navigationOptions =({ navigation, screenProps }) => ({
title: navigation.state.params?navigation.state.params.user:null,
headerRight:(
<Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
返回
</Text>
)
});
- 外界傳值
我們也可以將外界的參數傳遞給函數內部。下面的代碼采用結構賦值的方法,取出導航中狀態機的參數params,取出參數中的user,一樣可以拿到外界參數。
render() {
const {params} = this.props.navigation.state;
return (
<View>
<Text onPress={()=>this.props.navigation.goBack()}>Chat with {params.user}</Text>
</View>
);
}
2.2 TabNavigator案例
react-navigation組件除了可以用做頁面間的跳轉,當然也可以用做tab界面之間的切換。
- 導入react-navigation的子組件。這些組件分別是用于界面切換、跳轉、和標簽欄外置的擺放。
import {StackNavigator,TabNavigator,TabBarBottom} from 'react-navigation';
- 封裝一個TabBarItem,用于設置每個tab的圖片
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 } }
/>
)
}
}
- 導入封裝的TabBarItem組件 表示TabBar的每一項
import TabBarItem from './TabBarItem';
- 定義TabNavigator。定義幾個要切換的tab,每個tab設置好對應要顯示的屏幕。當然,從之前介紹的屬性可知,TabNavigator也擁有navigationOptions屬性,它由系統傳入navigation參數,之后來設置其他的子屬性。比如說tabBarLabel設置每個tab的標題,tabBarIcon設置選中和非選中的圖片。
之后再設置其它每個tab共同的屬性,用一個對象表示。
const Tab = TabNavigator({
Home:{
screen:HomeScreen,
navigationOptions:({navigation}) => ({
tabBarLabel:'首頁',
tabBarIcon:({focused,tintColor}) => (
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./imgs/ic_like_sel.png') }
selectedImage={require('./imgs/ic_mine_sel.png')}
/>
)
}),
},
Mine:{
screen:MineScreen,
navigationOptions:({navigation}) => ({
tabBarLabel:'我',
tabBarIcon:({focused,tintColor}) => (
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./imgs/ic_like_sel.png')}
selectedImage={require('./imgs/ic_like_sel.png')}
/>
)
}),
},
},
{
tabBarComponent:TabBarBottom,
tabBarPosition:'bottom',
swipeEnabled:false,
animationEnabled:false,
lazy:true,
tabBarOptions:{
activeTintColor:'#06c1ae',
inactiveTintColor:'#979797',
style:{backgroundColor:'#ffffff',},
labelStyle: {
fontSize: 20, // 文字大小
},
}
});
- 將tab放入到Navigator中
const Navigator = StackNavigator(
{
Tab:{screen:Tab},
},
{
navigationOptions:{
// title:'首頁',
headerBackTitle:null,
headerTintColor:'#333333',
showIcon:true,
swipeEnabled:false,
animationEnabled:false,
},
mode:'card',
});
- 在render方法中返回導航組件
export default class App extends Component<{}> {
render() {
return (
<Navigator/>
);
}
}
- HomePage和MinePage的代碼
StackNavigator還提供了onNavigationStateChange回調方法,用來監聽導航狀態的改變
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
export default class HomePage extends Component {
static navigationOptions = {
title:'首頁',
};
render() {
return(
<View style={{flex:1,backgroundColor:'yellow'}}>
<Text onPress={this._skip.bind(this)}>點擊跳轉</Text>
</View>
);
}
_skip() {
this.props.navigation.navigate("Mine");
}
}
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
export default class MinePage extends Component {
static navigationOptions = {
title:'我',
};
render() {
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text onPress={this._skip.bind(this)}>MinePage</Text>
</View>
);
}
/**
* 跳轉
*/
_skip() {
this.props.navigation.goBack();
}
}
2.3DreawerNavigator抽屜導航
DrawerNavigator是一個抽屜導航。設置方式其實跟設置Tab差不多。只是需要設定某些特殊的屬性。比如說drawerLabel、drawerIcon、drawerWidth、drawerPosition等等。
- 定義抽屜導航
HomeScreen與MineScree是導入外界的兩個界面,將它們定義到DrawerNavigator中。在抽屜導航中,將組件的屬性也一起設置好。
import {DrawerNavigator} from 'react-navigation';
import HomeScreen from './Pages/HomePage';
import MineScreen from './Pages/MinePage';
const MyApp = DrawerNavigator({
Home: {
screen: HomeScreen,
},
Mine: {
screen:MineScreen,
},
},
{
drawerWidth: 200, // 抽屜寬
drawerPosition: 'left', // 抽屜在左邊還是右邊
contentOptions: {
initialRouteName: 'Home', // 默認頁面組件
activeTintColor: 'white', // 選中文字顏色
activeBackgroundColor: '#ff8500', // 選中背景顏色
inactiveTintColor: '#666', // 未選中文字顏色
inactiveBackgroundColor: '#fff', // 未選中背景顏色
style: { // 樣式
}
}
}
);
- 在render方法中返回抽屜組件
export default class App extends Component<{}> {
// static navigationOptions={
// title:'app',
// gesturesEnabled:false,
// header:null,
// }
render() {
return (
<View style = {{flex:1,marginTop:20,}}>
<MyApp />
</View>
);
}
}
- 設置HomePage子頁面的屬性
一旦加入了導航組件react-navigation,那么其頁面就會有navigationOptions屬性。我們可以在這個屬性里面設置抽屜導航的樣式。
export default class HomePage extends Component<{}> {
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require('.././imgs/ic_like_sel.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
}
- 返回HomePage頁面要展示的組件
用navigation的navigate屬性可以跳轉到指定的頁面。如果指定的是DrawerOpen,意思就是打開抽屜。
render() {
return (
<View>
<Button
onPress={() => this.props.navigation.navigate('Mine')}
title="Go to Mine"
/>
<Button
onPress={()=>this.props.navigation.navigate('DrawerOpen')}
title="open the draw"
/>
</View>
);
}
- 設置樣式
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
- 設置MinePage頁面
MinePage頁面和HomePage頁面相差不大。只是做代碼演示而已,這里不再闡述
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image,
Button
} from 'react-native';
export default class MineScreen extends Component<{}> {
static navigationOptions = {
drawerLabel: 'Mine',
drawerIcon: ({ tintColor }) => (
<Image
source={require('.././imgs/ic_mine_sel.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<View>
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
<Button
onPress={()=>this.props.navigation.navigate('DrawerOpen')}
title="open the draw"
/>
</View>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
效果圖如下:
非寧靜無以致遠,非淡泊無以明志。在學習的道路上,多少會遇到泥濘挫折。我可以放慢腳步,但絕能不回頭,我的夢想,在路上。