本文是基於最新的react-navigation^2.9.1來書寫的。
如果遇到什麼問題可以在評論區回覆,或者加QQ羣397885169討論
因爲react-navigation
之前存在的問題相對較多,本文更新會稍慢,而且,我現在項目使用的是基於它封裝的react-native-router-flux
V4版本,現在也推薦給大家使用。在下面的文章中,我提供了簡易的Demo,react-native-router-flux
提供了更多的API和方法教給用戶使用,如果遇到不會的問題,歡迎加羣討論
react-native-router-flux使用技巧(API篇)
識兔,一款用來識別圖片的開源項目,在未來還會添加更多有意思的東西
react-navigation的Demo
react-navigation使用技巧(進階篇)
什麼是react-navigation?
react-native
從開源至今,一直存在幾個無法解決的毛病,偶爾就會復發讓人隱隱作痛,提醒你用的不是原生,其中包括列表的複用問題,導航跳轉不流暢的問題等等。
終於facebook坐不住了,在前一段時間開始推薦使用react-navigation
,並且在0.44發佈的時將之前一直存在的Navigator
廢棄了。react-navigation
是致力於解決導航卡頓,數據傳遞,Tabbar和navigator佈局,支持redux
。雖然現在功能還不完善,但基本是可以在項目中推薦使用的。
屬性
react-navigation
分爲三個部分。StackNavigator
類似頂部導航條,用來跳轉頁面和傳遞參數。TabNavigator
類似底部標籤欄,用來區分模塊。DrawerNavigator
抽屜,類似從App左側滑出一個頁面,在這裏不做講解。
下面會分開講解官網提供的配置方法,但順序可能會官網不一樣。
React-Navigation V2版使用教程
距離我上一個版本的react-navigation
教程已經有1年多的時間了,雖然一直在縫縫補補,但那個教程真的老了。正好react-navigation V2版本
也即將要正式發佈了,趁着這次機會重新梳理一下教程,並把之前的坑和遺憾填補一下。
我會將本文分成三部分,第一部分是使用小技巧,第二部分是介紹API,第三部分是常用屬性方法。
跳轉
navigate('Detail',{
title:'圖片詳情',
url:item.url,
});
Detail
:在StackNavigator中註冊的頁面,需要一一對應,才能跳轉到相應的頁面title
:在跳轉的頁面可以通過this.props.navigation.state.params.title
獲取到這個參數。當然這個參數可以隨便填寫,都可以通過this.props.navigation.state.params.xxx
獲取。
回調傳參
navigate('Detail',{
// 跳轉的時候攜帶一個參數去下個頁面
callback: (data)=>{
console.log(data); // 打印值爲:'回調參數'
}
});
const {navigate,goBack,state} = this.props.navigation;
// 在第二個頁面,在goBack之前,將上個頁面的方法取到,並回傳參數,這樣回傳的參數會重走render方法
state.params.callback('回調參數');
goBack();
自定義
項目中基本是沒可能用自帶的那個導航條的,自帶導航條左側的按鈕永遠是藍色的,如果我們需要更改按鈕顏色,就需要用到自定義的功能了。
const StackOptions = ({navigation}) => {
console.log(navigation);
let {state,goBack} = navigation;
// 用來判斷是否隱藏或顯示header
const visible= state.params.isVisible;
let header;
if (visible === true){
header = null;
}
const headerStyle = {backgroundColor:'#4ECBFC'};
const headerTitle = state.params.title;
const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white',fontWeight:'500'}
const headerBackTitle = false;
const headerLeft = (
<Button
isCustom={true}
customView={
<Icon
name='ios-arrow-back'
size={30}
color='white'
style={{marginLeft:13}}
/>
}
onPress={()=>{goBack()}}
/>
);
return {headerStyle,headerTitle,headerTitleStyle,headerBackTitle,headerLeft,header}
};
然後通過下面的方法調用就可以自定製導航了。
const MyApp = StackNavigator({
MyTab: {
screen: MyTab,
},
Detail: {
screen: Detail,
navigationOptions: ({navigation}) => StackOptions({navigation})
},
)};
在頁面中使用的時候,在跳轉頁面的時候需要傳遞title
參數,才能看到效果哦。
自定義tabbar
早上有人問我,tabbar的圖標可不可以使用原圖,選中狀態下可不可以設置其他圖標。研究了一下官方文檔,發現tabBarIcon
除了tintColor
還有另一個屬性,用來判斷選中狀態的focused
。
tabBarIcon: ({tintColor,focused}) => (
focused
?
<Image
source={{uri : '識兔'}}
style={tabBarIcon}
/>
:
<Image
source={{uri : '乾貨'}}
style={[tabBarIcon, {tintColor: tintColor}]}
/>
),
通過判斷focused
,選中狀態下使用識兔
圖標,未選中狀態使用乾貨
圖標。
如果想使用圖標原來的樣子,那就將style
的tintColor
去掉,這樣就會顯示圖標原本的顏色。
再封裝
export const TabOptions = (tabBarTitle,normalImage,selectedImage,navTitle) => {
// console.log(navigation);
const tabBarLabel = tabBarTitle;
console.log(navTitle);
const tabBarIcon = (({tintColor,focused})=> {
return(
focused
?
<Image
source={{uri : normalImage}}
style={[TabBarIcon, {tintColor: tintColor}]}
/>
:
<Image
source={{uri : selectedImage}}
style={[TabBarIcon, {tintColor: tintColor}]}
/>
)
});
const headerTitle = navTitle;
const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white'};
// header的style
const headerStyle = {backgroundColor:'#4ECBFC'};
return {tabBarLabel,tabBarIcon,headerTitle,headerTitleStyle,headerStyle};
};
在static中使用this方法
我之前文章中是將navaigationOptions
的方法寫在了app.js
中,沒有在頁面中通過static navaigationOptions
來初始化頁面,這段時間剛好有人問,所以在這裏就寫一下該怎麼弄。
首先需要在componentDidMount(){}中動態的添加點擊事件
屬性給params
componentDidMount(){
this.props.navigation.setParams({
title:'自定義Header',
navigatePress:this.navigatePress
})
}
navigatePress = () => {
alert('點擊headerRight');
console.log(this.props.navigation);
}
接下來就可以通過params方法來獲取點擊事件了
static navigationOptions = ({ navigation, screenProps }) => ({
title: navigation.state.params?navigation.state.params.title:null,
headerRight:(
<Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
返回
</Text>
)
});
讓安卓實現push動畫
之前我羣裏的討論怎麼讓安卓實現類似iOS的push動畫,後來翻看官方issues的時候,真的發現了實現push動畫的代碼,在這裏共享下
// 先引入這個方法
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';
// 在StackNavigator配置headerMode的地方,使用transitionConfig添加
{
headerMode: 'screen',
transitionConfig:()=>({
screenInterpolator:CardStackStyleInterpolator.forHorizontal,
})
}
關於goBack返回指定頁面
react-navigation
是提供了goBack()到指定頁面的方法的,那就是在goBack()中添加一個參數,但當你使用goBack('Main')
的時候,你會發現並沒有跳轉,原因是react-navigation默認goBack()中的參數是系統隨機分配的key
,而不是手動設置的routeName
,而方法內部又沒有提供可以獲得key
的方法,所以這裏只能通過修改源碼將key
換成routeName
了。
下面的內容直接引用了hello老文
的內容
把項目/node_modules/react-navigation/src/routers/StackRouter.js文件裏的
const backRoute = state.routes.find((route: *) => route.key === action.key);
改成 const backRoute = state.routes.find(route => route.routeName === action.key);
但不是很完美, 這裏的component要填想返回的組件的前一個組件的routeName, 比如你的棧裏順序是home1, home2, home3, home4, 在home4裏要返回home2, 使用this.props.navigation.goBack('home3');; 並且又會帶出一個問題: goBack()方法沒反應了, 必須加個null進去, 寫成goBack(null)...
關於goBack返回指定頁面的修改完善版
if (action.type === NavigationActions.BACK) {
let backRouteIndex = null;
if (action.key) {
const backRoute = state.routes.find(
/* $FlowFixMe */
/* 修改源碼 */
route => route.routeName === action.key
/* (route: *) => route.key === action.key */
);
/* $FlowFixMe */
console.log('backRoute =====',backRoute);
backRouteIndex = state.routes.indexOf(backRoute);
console.log('backRoute =====',backRouteIndex);
}
if (backRouteIndex == null) {
return StateUtils.pop(state);
}
if (backRouteIndex >= 0) {
return {
...state,
routes: state.routes.slice(0, backRouteIndex+1),
index: backRouteIndex - 1 + 1,
};
}
}
感謝羣友conan
的貢獻,將源碼改成上面的樣子,就可以使用goBack()
返回指定頁面了,這樣的優點不言而喻,但缺點就是每次調用goBack()
,如果只是簡單的返回上一頁需要加上null
參數,類似這樣goBack(null)
,
如果這樣修改,在滑動返回的時候,會有很大機率讓項目卡死,請注意使用該方法,推薦集成redux。
關於快速點擊會導致多次跳轉的問題解決辦法
感謝羣友編程大叔
的貢獻,如果想解決快速點擊跳轉的問題,需要修改部分源碼。
修改react-navigation目錄下,scr文件夾中的addNavigationHelpers.js文件
,可以直接替換成下面的文本,也可以查看原版鏈接
export default function<S: *>(navigation: NavigationProp<S, NavigationAction>) {
// 添加點擊判斷
let debounce = true;
return {
...navigation,
goBack: (key?: ?string): boolean =>
navigation.dispatch(
NavigationActions.back({
key: key === undefined ? navigation.state.key : key,
}),
),
navigate: (routeName: string,
params?: NavigationParams,
action?: NavigationAction,): boolean => {
if (debounce) {
debounce = false;
navigation.dispatch(
NavigationActions.navigate({
routeName,
params,
action,
}),
);
setTimeout(
() => {
debounce = true;
},
500,
);
return true;
}
return false;
},
/**
* For updating current route params. For example the nav bar title and
* buttons are based on the route params.
* This means `setParams` can be used to update nav bar for example.
*/
setParams: (params: NavigationParams): boolean =>
navigation.dispatch(
NavigationActions.setParams({
params,
key: navigation.state.key,
}),
),
};
}
安卓上,使用TextInput的時候會讓TabBar頂起來的解決辦法
最簡單的解決辦法就是在android
目錄中,添加一句話
目錄:android/app/src/main/AndroidManifest.xml
中,添加
android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"
ps:在iOS下如果想一勞永逸的解決鍵盤問題,請使用IQKeyBoardManager
。
API
createSwitchNavigator
SwitchNavigator
的目的是一次只顯示一個屏幕。默認情況下,它不處理回退操作,並在您切換時將路由重置爲默認狀態。這是我們從登錄流程(包含註冊,登錄,忘記密碼等)到主屏幕的必要流程。這個方法在1.x中叫做
SwitchNavigator
,在2.x中統一命名爲createSwitchNavigator
createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig);
RouteConfigs
路由的配置表,詳細配置可以參考下面的
createStackNavigator
SwitchNavigatorConfig
SwitchNavigator
屬性
initialRouteName
- 第一次加載時初始選項卡路由的routeName。resetOnBlur
- 切換離開屏幕時,重置所有嵌套導航器的狀態。默認爲true
。paths
- 提供routeName
到path
的深度鏈接,它會覆蓋RouteConfigs
中設置的路徑。backBehavior
- 後退按鈕是否會導致標籤切換到初始路由?如果是,則設置爲initialRoute
,否則none
。默認爲none
。
export default createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
createStackNavigator
配置路由屬性和參數
這個方法在1.x中叫做
StackNavigator
,在2.x中統一命名爲createSwitchNavigator
createStackNavigator(RouteConfigs, StackNavigatorConfig);
RouteConfigs
screen
- 對應界面名稱,是一個React
組件path
- 深度鏈接路徑,從其他App或者web跳轉到該App需要設置該路徑navigationOptions
- 用於屏幕的默認導航選項
StackNavigatorConfig
可選的路由屬性
initialRouteName
- 設置默認屏幕。必須爲路由配置中的某個screen
。initialRouteParams
- 初始路由路線的參數。navigationOptions
- 用於屏幕的默認導航選項。paths
- 覆蓋路由配置中設置的路徑的映射。
可選的視覺選項
-
mode
- 定義渲染和轉換的樣式card
- 使用標準的iOS和Android屏幕轉換。這是默認屬性。modal
- 使屏幕從底部滑入,這是一種常見的iOS模式。只適用於iOS,對Android沒有影響。
-
headerMode
- 定義如何呈現標題float
- 在屏幕更改時渲染保留在頂部的單個標題和動畫。這是iOS上的常見效果。screen
- 每個屏幕都附有一個標題,標題與屏幕一起淡入和淡出。這是Android上的常見效果。none
- 不會顯示標題。
-
headerTransitionPreset
- 指定標題在headerMode: float
啓用時應該如何從一個屏幕切換到另一個屏幕。fade-in-place
- 標題組件在不移動的情況下淡入淡出,類似於iOS的Twitter,Instagram和Facebook應用程序。這是默認值。uikit
- iOS的默認效果。
-
cardStyle
- 使用此道具覆蓋或擴展堆棧中單個卡的默認樣式。 -
transitionConfig
- 函數返回與默認屏幕轉換合併的對象(查看類型定義中的TransitionConfig )。提供的函數將傳遞以下參數:transitionProps
- 新屏幕的過渡轉換。prevTransitionProps
- 舊屏幕的過渡轉換。isModal
- 指定屏幕是否爲模態。
-
onTransitionStart
- 跳轉動畫即將開始時要調用的函數。 -
onTransitionEnd
- 跳轉動畫完成後調用的函數。
navigationOptions
導航頁面的屬性和方法
-
title
- 可用作的headerBackTitle
的標題。此外,將用作tabBarLabel
(如果嵌套在TabNavigator中)或drawerLabel
(如果嵌套在DrawerNavigator中)的回退標題。 -
header
- 返回一個React
元素,用來作爲標題。設置null
會隱藏標題。 -
headerTitle
- 可以傳入字符串,React Element
,React Component
。默認是用上面的title
作爲標題。當使用Component
時,它接受allowFontScaling
,style
和children
作爲屬性。title
會被放在children
中。 -
headerTitleAllowFontScaling
- 標題字體是否應該縮放以遵循系統設置。默認值爲true。 -
headerBackImage
- 接受React Element
或者Component
用來顯示自定義的後退按鈕中的圖片。當使用組件時,它會得到(tintColor,title)
參數。默認爲react-navigation/views/assets/back-icon.png
路徑下的圖片,這是區分平臺的默認圖標。 -
headerBackTitle
- iOS上後退按鈕使用的文字,傳遞null
會禁用標籤。默認爲前一場景headerTitle
。 -
headerTruncatedBackTitle
- 當後退按鈕使用的標題字符串headerBackTitle
不適合屏幕時(比如說文字過長),會默認顯示Back
。 -
headerRight
- 接受React Element
將會顯示在標題的右側。 -
headerLeft
- 接受React Element
或者React Component
將會顯示在標題的左側。當傳遞一個組件的時候,會得到(onPress,title,titleStyle
還有更多,請參考Header.js
以獲得完整的列表)。 -
headerStyle
- 標題的樣式 -
headerForceInset
- 允許將forceInset對象傳遞給標題中,使用的內部SafeAreaView。 -
headerTitleStyle
- 標題組件的樣式 -
headerBackTitleStyle
- 標題上後退按鈕文字樣式 -
headerTintColor
- 標題組件的色調 -
headerPressColorAndroid
- 材質紋波的顏色(僅限Android> = 5.0) -
headerTransparent
- 默認爲false
。如果爲true
標題將沒有背景,除非你明確提供了headerStyle
或headerBackground
。 -
headerBackground
- 將此與headerTransparent一起使用,以提供一個組件在標題的背景中呈現。例如,您可以將其用於模糊視圖,以創建半透明標題。 -
gesturesEnabled
- 是否可以使用手勢來返回到上一頁。在iOS上默認爲true
,在Android上爲false
。 -
gestureResponseDistance
- 用於覆蓋觸摸從屏幕邊緣開始識別手勢的距離的對象。它具有以下屬性:horizontal
- number - 水平方向的距離。默認爲25。vertical
- number - 垂直方向的距離。默認爲135。
-
gestureDirection
- 傳遞字符串用來覆蓋關閉手勢的方向。default
爲正常行爲或inverted
從右到左滑動。
Navigator Props
由StackNavigator(...)創建的導航器組件採用以下道具:
screenProps
- 將其他選項傳遞給子屏幕
createTabNavigator
createTabNavigator
已棄用。請改用createBottomTabNavigator
和/或createMaterialTopTabNavigator
。
createBottomTabNavigator
屏幕底部的簡單標籤欄,可讓您在不同路由之間切換。路由是被懶惰初始化的 - 它們的屏幕組件直到第一次選中時纔會初始化。
這個方法在1.x中叫做
TabNavigator
,在2.x中統一命名爲createBottomTabNavigator
createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);
RouteConfigs
屬性請參考
createStackNavigator
。
它的navigationOptions
和createStackNavigator
不一樣,下面會有說明。
BottomTabNavigatorConfig
-
initialRouteName
- 第一次加載時初始選項卡路由的routeName。 -
order
- 定義選項卡順序的routeNames數組。 -
paths
- 提供routeName
到path
的深度鏈接,它會覆蓋RouteConfigs
中設置的路徑。 -
backBehavior
- 後退按鈕是否會導致標籤切換到初始路由?如果是,則設置爲initialRoute
,否則none
。默認爲initialRoute
。 -
tabBarComponent
- Options,覆蓋用作標籤欄的組件。 -
tabBarOptions
- 標籤欄具有如下屬性:activeTintColor
- 活動選項卡的標籤和圖標顏色。(選中)activeBackgroundColor
- 活動選項卡的背景顏色。(選中)inactiveTintColor
- 非活動選項卡的標籤和圖標顏色。(未選中)inactiveBackgroundColor
- 非活動選項卡的背景顏色。(未選中)showLabel
- 是否顯示標籤,默認爲true
。style
- 標籤欄的樣式。labelStyle
- 標籤欄文字的樣式。tabStyle
- 選項卡的樣式。allowFontScaling
- 標題字體是否應該縮放以遵循系統設置。默認值爲true。
navigationOptions
標籤欄的屬性和方法
-
title
- 通用標題可以用作headerTitle
和tabBarLabel
。 -
tabBarVisible
- 顯示或隱藏底部標籤欄,默認爲true
,不隱藏。 -
tabBarIcon
-React Element
或給定{focused:boolean,tintColor:string}
的函數返回一個React.Node
,用來顯示在標籤欄中。 -
tabBarLabel
- 接收字符串、React Element
或者給定{focused:boolean,tintColor:string}
的函數返回一個React.Node
,用來顯示在標籤欄中。如果未定義,會使用title
作爲默認值。如果想要隱藏,可以參考上面的tabBarOptions.showLabel
。 -
tabBarOnPress
- 標籤欄點擊事件回調,接受一個對象,其中包含如下:
tabBarObj 2.png
tabBarOnPress: async (obj: any) => {
console.log(obj);
try {
const userData = await AsyncStorage.getItem('USER_INFO');
if (userData) {
obj.defaultHandler();
}
else {
obj.navigation.navigate('Login');
}
} catch (e) {
Toast.show(e.message, 'center', 1000);
}
}
createMaterialTopTabNavigator
實現了類似
react-native-scrollable-tab-view
的左右滾動效果,但每個tab頁是沒有懶加載的,就是說,當使用這個生成導航的時候,每個頁面都會初始化,對內存影響較大。
這個導航是基於react-native-tab-view
實現的,如果有需要可以研究。
createMaterialTopTabNavigator(RouteConfigs, TabNavigatorConfig);
RouteConfigs
屬性請參考
createStackNavigator
。
TabNavigatorConfig
-
initialRouteName
- 第一次加載時初始選項卡路由的routeName。 -
order
- 定義選項卡順序的routeNames數組。 -
paths
- 提供routeName
到path
的深度鏈接,它會覆蓋RouteConfigs
中設置的路徑。 -
backBehavior
- 後退按鈕是否會導致標籤切換到初始路由?如果是,則設置爲initialRoute
,否則none
。默認爲initialRoute
。 -
swipeEnabled
- 是否允許在標籤之間滑動。 -
animationEnabled
- 改變標籤時是否使用動畫。 -
configureTransition
- 給定currentTransitionProps和nextTransitionProps返回一個描述選項卡之間動畫的配置對象的函數。 -
initialLayout
- 包含初始height
和可選對象width
,可以傳遞以防止react-native-tab-view
出現一幀的延遲。 -
tabBarComponent
- Options,覆蓋用作標籤欄的組件。 -
tabBarOptions
- 標籤欄具有如下屬性:activeTintColor
- 活動選項卡的標籤和圖標顏色。(選中)inactiveTintColor
- 非活動選項卡的標籤和圖標顏色。(未選中)showIcon
- 是否顯示標籤圖標,默認爲false
。showLabel
- 是否顯示標籤,默認爲true
。upperCaseLabel
- 是否使標籤大寫,默認爲true
。pressColor
- 紋波的顏色(僅限Android> = 5.0)。pressOpacity
- 按下標籤的不透明度(僅iOS和Android <5.0)。scrollEnabled
- 是否啓用可滾動標籤。tabStyle
- 選項卡的樣式。indicatorStyle
- 選項卡指示符的樣式(選項卡底部線的顏色)。labelStyle
- 標籤欄文字的樣式。iconStyle
- 選項卡圖標的樣式。style
- 標籤欄的樣式。allowFontScaling
- 標題字體是否應該縮放以遵循系統設置。默認值爲true
。
navigationOptions
title
- 通用標題可以用作headerTitle
和tabBarLabel
。swipeEnabled
- 如果未設置,則遵循TabNavigatorConfig
選項swipeEnabled
。啓用或禁用標籤之間的滑動操作爲true
或false
。tabBarIcon
-React Element
或給定{focused:boolean,tintColor:string}
的函數返回一個React.Node
,用來顯示在標籤欄中。tabBarLabel
- 接收字符串、React Element
或者給定{focused:boolean,tintColor:string}
的函數返回一個React.Node
,用來顯示在標籤欄中。如果未定義,會使用title
作爲默認值。如果想要隱藏,可以參考上面的tabBarOptions.showLabel
。tabBarOnPress
- 標籤欄點擊事件回調,接受一個對象,其中包含如下:
tabBarObj 2.png
tabBarOnPress: async (obj: any) => {
console.log(obj);
try {
const userData = await AsyncStorage.getItem('USER_INFO');
if (userData) {
obj.defaultHandler();
}
else {
obj.navigation.navigate('Login');
}
} catch (e) {
Toast.show(e.message, 'center', 1000);
}
}
createDrawerNavigator
創建側邊欄導航,有一些坑,需要用過才知道。
createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
RouteConfigs
屬性請參考
createStackNavigator
。
DrawerNavigatorConfig
-
drawerWidth
- 抽屜的寬度或返回一個新的函數。 -
drawerPosition
- 抽屜出現的方向left
或right
,默認left
。 -
contentComponent
- 用於呈現抽屜內容的組件,例如導航項。接收navigation
抽屜的屬性。默認爲DrawerItems
。有關更多信息,請參見下文。 -
contentOptions
- 配置抽屜內容,請參見下文。 -
useNativeAnimations
- 啓用本地動畫。默認是true
。 -
drawerBackgroundColor
- 設置抽屜的背景背景。默認是white。 -
initialRouteName
- 第一次加載時初始選項卡路由的routeName。 -
order
- 定義選項卡順序的routeNames數組。 -
paths
- 提供routeName
到path
的深度鏈接,它會覆蓋RouteConfigs
中設置的路徑。 -
backBehavior
- 後退按鈕是否會導致標籤切換到初始路由?如果是,則設置爲initialRoute
,否則none
。默認爲initialRoute
。
contentComponent
提供自定義的抽屜效果
抽屜的默認組件是可滾動的,只包含RouteConfig中路由的鏈接。您可以輕鬆地覆蓋默認組件,以向抽屜中添加頁眉,頁腳或其他內容。默認情況下,抽屜可滾動並支持iPhone X安全區域。如果您自定義內容,請務必將內容包裝在SafeAreaView中
DrawerItems
的contentOptions
-
items
- 路由數組,可以修改或覆蓋。 -
activeItemKey
- 識別活動路線的key。 -
activeTintColor
- 活動標籤的標籤和圖標顏色。(選中) -
activeBackgroundColor
- 活動標籤的背景顏色。(選中) -
inactiveTintColor
- 不活動標籤的標籤和圖標顏色。(未選中) -
inactiveBackgroundColor
- 不活動標籤的背景顏色。(未選中) -
onItemPress(route)
- 按下某個Item時調用的函數。 -
itemsContainerStyle
- item內容的樣式。 -
itemStyle
- 單個Item
樣式,其中可以包含圖標和標籤。 -
labelStyle
- 當標籤是字符串時,會覆蓋文字的樣式。 -
activeLabelStyle
- 當標籤是字符串時,會覆蓋選中的文字樣式。 -
inactiveLabelStyle
- 當標籤是字符串時,會覆蓋未選中的文字樣式。 -
iconContainerStyle
- 用來覆蓋icon的樣式
Screen Navigation Options
-
title
- 通用標題可以用作headerTitle
和tabBarLabel
。 -
drawerLabel
- 可以傳入字符串,React Element或給定{focused:boolean,tintColor:string}
的函數返回一個React.Node
,用來顯示在抽屜邊欄中。當不設置時,默認使用title
。 -
drawerIcon
- React Element或給定{focused:boolean,tintColor:string}
的函數返回一個React.Node
,用來顯示在抽屜邊欄中。 -
drawerLockMode
- 指定抽屜的鎖定模式。這也可以通過在頂級路由器上使用screenProps.drawerLockMode動態更新。
enum('unlocked', 'locked-closed', 'locked-open')
createMaterialBottomTabNavigator
這個方法在2.0正式版中被砍掉了,但官方文檔沒有更新,如果喜歡material
風格,可以參考react-native-material-bottom-navigation
常用屬性方法
這部分會分爲
createStackNavigator
和createDrawerNavigator
兩部分,因爲它們屬性不太一樣。
createStackNavigator
常用方法
在新版的
react-navigation
中實現了很多常用的api,比如說push
,pop
,popToTop
等常用方法,在本文中會將屬性和使用方法簡單說明。
NavigationActions
Navigate
- 用來跳轉到其他路由的方法routeName
- String - 必須 - 在RouteConfigs
中註冊過的路由名稱params
- Object - 可選 - 傳遞的參數action
- Object - 可選 - (高級)如果屏幕是導航器,則在子路由器中運行的子操作。本文檔中描述的任何一項操作都可以設置爲子操作。key
- String - 可選 - 要導航到的路線的標識符。如果它已經存在,則返回到此路線。
import { NavigationActions } from 'react-navigation';
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute' }),
});
this.props.navigation.dispatch(navigateAction);
-
Back
- 用來返回到上一個路由或其他路由Key
- String | null - 如果設置,導航將從給定的鍵返回。如果爲空,導航將返回到上一級。
import { NavigationActions } from 'react-navigation';
const backAction = NavigationActions.back({
key: 'Profile',
});
this.props.navigation.dispatch(backAction);
SetParams
在調用SetParams時,路由器將產生一個新的狀態,該狀態已經改變了由
key
標識的特定路由參數
* `params` - Object - 可選 - 新的參數被合併到現有的路徑參數中。
* `key` - String - 必須 - 獲取新參數的路由鍵。
import { NavigationActions } from 'react-navigation';
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },
key: 'screen-123',
});
this.props.navigation.dispatch(setParamsAction);
Reset
- 重置路由
Reset
操作將重置整個導航狀態並將其替換爲新的導航。
* `index` - number - 必須 - 導航中`routes`活動路由的索引`state`。
* `actions` - array - 必須 - 將替換導航數組。
* `key` - string | null - 可選 - 如果設置,具有給定鍵的導航器將重置。如果爲null,則根導航器將被重置。
import { StackActions, NavigationActions } from 'react-navigation';
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Profile' })],
});
this.props.navigation.dispatch(resetAction);
Replace
- 用新的route替換當前的route
Replace操作將給定
key
上的路線替換爲另一條路線。
* `key` - string - 必須 - 要替換路由的`key`。
* `newKey` - string - 用於替換路由的`key`。如果未提供,則自動生成。
* `routeName` - string - 用於替換路由的`routeName`。
* `params` - object - 要傳入替換路由的參數。
* `action` - object - 可選的子操作。
Push
- 入棧
Push
操作會在堆棧頂部添加一條路徑並向前導航。這與之前的不同之處在於,如果某個組件已經存在路由中,navigate
則會彈出到堆棧中的較早版本。Push
將始終添加在頂部,因此可以多次安裝組件。
* `routeName` - string - 要跳轉路由的`routeName`。
* `params` - object - 傳遞的參數,可以通過(this.props.navigation.state.params)找到。
* `action` - 子操作。
pop(n)
- 出棧
Pop
操作將使您回到堆棧中的前一個屏幕。n
參數允許您指定要多少個屏幕出棧。
* `n` - number - 要出棧的屏幕數量。
PopToTop
- 回到棧頂
PopToTop
操作會將您帶回堆棧中的第一個屏幕,解除所有其他屏幕。它的功能與StackActions.pop({n: currentIndex})
類似。
----------------------------------------------新老版本的分割線--------------------------------------------------------
screenProps
之前是沒有介紹這個屬性的,但經過這麼久發現,很多人都不知道這個屬性,不知道它能幹嘛,在這裏我就簡單的介紹下
screenProps
:react-navigation自帶的一個屬性,屬於navigationOptions
的一個屬性,可以全局控制navigationOptions
中的某些值,比如說你想做換膚功能,修改這個屬性絕對是最簡單的方式。
// 假設App就是項目中的入口文件,如果還不知道,可以看下Demo,在這裏我將主題色通過screenProps屬性修改成'red'
<App screenProps={{themeColor:'red'}}>
// 在頁面中就可以通過screenProps來直接改變了,這個在Demo
中的Test2裏面
static navigationOptions = ({navigation,screenProps}) => ({
// 這裏面的屬性和App.js的navigationOptions是一樣的。
headerStyle:{backgroundColor:screenProps?
screenProps.themeColor:
'#4ECBFC'},
)
})
StackNavigator 基礎用法/屬性介紹
const MyApp = StackNavigator({
// 對應界面名稱
MyTab: {
screen: MyTab,
},
Detail: {
screen: Detail,
navigationOptions:{
headerTitle:'詳情',
headerBackTitle:null,
}
},
}, {
headerMode: 'screen',
});
導航配置
screen
:對應界面名稱,需要填入import
之後的頁面。
navigationOptions
:配置StackNavigator的一些屬性。
title
:標題,如果設置了這個導航欄和標籤欄的title就會變成一樣的,所以不推薦使用這個方法。header
:可以設置一些導航的屬性,當然如果想隱藏頂部導航條只要將這個屬性設置爲null
就可以了。headerTitle
:設置導航欄標題,推薦用這個方法。headerBackTitle
:設置跳轉頁面左側返回箭頭後面的文字,默認是上一個頁面的標題。可以自定義,也可以設置爲null
headerTruncatedBackTitle
:設置當上個頁面標題不符合返回箭頭後的文字時,默認改成"返回"。(上個頁面的標題過長,導致顯示不下,所以改成了短一些的。)headerRight
:設置導航條右側。可以是按鈕或者其他。headerLeft
:設置導航條左側。可以是按鈕或者其他。headerStyle
:設置導航條的樣式。背景色,寬高等。如果想去掉安卓導航條底部陰影可以添加elevation: 0
,iOS下用shadowOpacity: 0。headerTitleStyle
:設置導航條文字樣式。安卓上如果要設置文字居中,只要添加alignSelf:'center'
就可以了。在安卓上會遇到,如果左邊有返回箭頭導致文字還是沒有居中的問題,最簡單的解決思路就是在右邊也放置一個空的按鈕。
在最新版本的react-navigation
中,安卓居中可以使用 flex:1, textAlign: 'center'
來實現。
headerBackTitleStyle
:設置導航條返回文字樣式。headerTintColor
:設置導航欄文字顏色。總感覺和上面重疊了。headerPressColorAndroid
:安卓獨有的設置顏色紋理,需要安卓版本大於5.0gesturesEnabled
:是否支持滑動返回手勢,iOS默認支持,安卓默認關閉gestureResponseDistance
:對象覆蓋觸摸從屏幕邊緣開始的距離,以識別手勢。 它需要以下屬性:- horizontal - number - 水平方向的距離 默認爲25。
- vertical - number - 垂直方向的距離 默認爲135。
// 設置滑動返回的距離
gestureResponseDistance:{horizontal:300},
注:beta13新出的東西,挺有意思,以後可以手動控制返回了
導航視覺效果
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界面。
TabNavigator 基礎用法/屬性介紹
const MyTab = TabNavigator({
ShiTu: {
screen: ShiTu,
navigationOptions:{
tabBarLabel: '識兔',
tabBarIcon: ({tintColor}) => (
<Image
source={{uri : '識兔'}}
style={[tabBarIcon, {tintColor: tintColor}]}
/>
),
},
}, {
tabBarPosition: 'bottom',
swipeEnabled:false,
animationEnabled:false,
tabBarOptions: {
style: {
height:49
},
activeBackgroundColor:'white',
activeTintColor:'#4ECBFC',
inactiveBackgroundColor:'white',
inactiveTintColor:'#aaa',
showLabel:false,
}
});
屏幕導航配置
screen
:和導航的功能是一樣的,對應界面名稱,可以在其他頁面通過這個screen傳值和跳轉。navigationOptions
:配置TabNavigator的一些屬性
title
:標題,會同時設置導航條和標籤欄的title,還是不推薦這種方式。tabBarVisible
:是否隱藏標籤欄。默認不隱藏(true)tabBarIcon
:設置標籤欄的圖標。需要給每個都設置。tabBarLabel
:設置標籤欄的title。推薦這個方式。tabBarOnPress
:設置tabBar的點擊事件,內部提供了兩個屬性,一個方法(obj)。beta13新添加的方法,使用方式有些奇葩,如果想要使用,請參照下面的代碼
tabBarOnPress:(obj)=>{
console.log(obj);
obj.jumpToIndex(obj.scene.index)
},
標籤欄配置
tabBarPosition
:設置tabbar的位置,iOS默認在底部,安卓默認在頂部。(屬性值:'top','bottom')swipeEnabled
:是否允許在標籤之間進行滑動。animationEnabled
:是否在更改標籤時顯示動畫。lazy
:是否根據需要懶惰呈現標籤,而不是提前製作,意思是在app打開的時候將底部標籤欄全部加載,默認false,推薦改成true哦。initialRouteName
: 設置默認的頁面組件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
:圖標的樣式。
ps:很多人問我,爲什麼安卓上的tabbar文字會下移, 是因爲安卓比iOS多了一個屬性,就是iconStyle
,通過設置labelStyle
和iconStyle
兩個樣式,外加style
的高度,來使效果更佳合理.
總結
react-navigation纔開始用的時候感覺是複雜的,但用的多了,會感覺真的很不錯。
如果在文章中有什麼不懂的問題,歡迎在評論區評論,也可以發私信,加QQ羣397885169一起討論哦