入門:
React Navigation誕生于React Native社區需要一個由javascript編寫的擴展且易于使用的導航解決方案。目前react-navigation已經更新到3.x版本了。如果對react-navigation不了解的可以先看React Native Express(http://www.reactnativeexpress.com/)前4章
什么是導航器:
導航器可以看作是一個普通的React組件,可以通過導航器來定義APP的導航結構,導航器還可以渲染通用元素,比如配置標題欄和選項卡欄,在React-navigation中有一下三種類型的導航器:createStackNavigator,createSwitchNavigator,createDrawerNavigator,createBottomTabNavigator,createMaterialBottomTabNavigator,createMaterialTopTabNavigator等,詳情請看官網:https://reactnavigation.org/docs/en/material-top-tab-navigator.html
兩個與導航器相關的概念:
- navigation prop(屏幕導航屬性):通過navigation可以完成屏幕之間的調度操作
- navigationOptions(屏幕導航選項):通過navigationOptions可以定制導航器顯示屏幕的方式(頭部標題,選項卡標簽等)
Navigation prop 詳解
當導航器中的屏幕被打開時,會收到一個navigation prop,navigation包含以下功能
- navigate - 轉跳到其他界面
class ProfileScreen extends React.Component {
render() {
return (
<Button
onPress={()=>navigation('Profile', {name: '稻城'})}
title="Set title name to '稻城'"
/>
);
}
}
- goback - 關閉當前界面
class ProfileScreen extends React.Component {
render() {
return (
<Button
onPress={goBack()}
title="Set title name to '稻城'"
/>
);
}
}
- addListener - 訂閱導航生命周期的更新
- isFocused - 一個函數返回true或false,查詢屏幕是否獲取焦點
- state - 屏幕當前的state
class ProfileScreen extends React.Component {
render() {
const params = this.props.navigation.state
return <Text>Name: {params.name}</Text>;
}
}
- setParams - 改變路由的params
class ProfileScreen extends React.Component {
render() {
return (
<Button
onPress={() => this.props.navigation.setParams({ name: 'Lucy' })}
title="Set title name to '稻城'"
/>
);
}
}
- dispatch - 向路由發送一個action
import { NavigationActions } from 'react-navigation';
const navigateAction = 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(navigateAction);
- dangerouslyGetParent - 返回父導航器的函數
navigation有一下幾種方式:
- push - 將新路由推入堆棧
navigation.push(routeName, params, action)
- pop - 回到堆棧中
navigation.pop(n) //n為在路由堆棧中的第幾個screen
- popToTop - 轉到堆棧頂部
navigation.popToTop()
- replace - 用新的路由替換當前路由
navigation.replace(routeName, params, action)
- reset - 刪除所有的navigation state并且使用這個reset的代替
navigation.reset([NavigationActions.navigate({ routeName: 'Profile' })], 0
- dismiss - 關閉當前堆棧
navigation.dismiss()
createStackNavigator的使用
為APP提供一種在屏幕之間轉換的方式,其中每個新屏幕都放置在堆棧頂部。默認情況下,堆棧導航器配置為具有熟悉的iOS和Android外觀:新的屏幕從iOS右側滑入,從Android底部淡入。在iOS上,堆棧導航器也可以配置為模式樣式,屏幕從底部滑入。
API的定義
createStackNavigator(RouteConfigs, StackNavigatorConfig);
RouteConfigs
route configs對象是從路由名稱到路由配置的映射,它告訴導航器為該路由提供什么。
createStackNavigator({
// For each screen that you can navigate to, create a new entry like this:
Profile: {
// `ProfileScreen` is a React component that will be the main content of the screen.
screen: ProfileScreen,
// When `ProfileScreen` is loaded by the StackNavigator, it will be given a `navigation` prop.
// Optional: When deep linking or using react-navigation in a web app, this path is used:
path: 'people/:name',
// The action and route params are extracted from the path.
// Optional: Override the `navigationOptions` for the screen
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.name}'s Profile'`,
}),
},
...MyOtherRoutes,
});
StackNavigatorConfig
路由器的選項
- initialRouteName - 設置堆棧的默認屏幕。必須匹配路由配置中的一個鍵
- initialRouteParams - 初始路線的參數
- initialRouteKey - 初始路由的可選標識符
- defaultNavigationOptions - 用于屏幕的默認導航選項
- paths - 路徑配置中設置的路徑的覆蓋映射
視覺選項
- mode - 定義渲染和過渡的樣式:
- card - 使用標準的iOS和Android屏幕過渡。這是默認值。
- modal - 使屏幕從底部滑入,這是一種常見的iOS模式。僅適用于iOS,對Android沒有影響。
- headerMode - 指定標頭的呈現方式:
- float - 渲染單個標題,保持在頂部,并在屏幕更改時設置動畫。這是iOS上的常見模式。
- screen - 每個屏幕都附有一個標題,標題與屏幕一起淡入淡出。這是Android上的常見模式。
- none - 不會呈現標題。
- headerBackTitleVisible- 提供了合理的默認值,以確定后退按鈕標題是否可見,但如果要覆蓋可以使用true或false在此選項中。
- headerTransitionPreset- 指定headerMode: float啟用時標頭應如何從一個屏幕轉換到另一個屏幕。
- fade-in-place - 標題組件交叉淡入淡出而不移動,類似于iOS的Twitter,Instagram和Facebook應用程序。這是默認值。
- uikit - iOS的默認行為的近似值。
- headerLayoutPreset - 指定如何布置標題組件。
- left - 將標題錨定在左側,靠近后退按鈕或其他左側組件。這是Android上的默認設置。在iOS上使用時,隱藏標題后退標題。左側組件中的內容將溢出標題下方,如果您需要調整此內容,則可以使用headerLeftContainerStyle和headerTitleContainerStyle。此外,此對齊與此不兼容headerTransitionPreset: 'uikit'。
- center - 將標題居中,這是iOS上的默認設置。
- cardStyle - 使用此prop可以覆蓋或擴展堆棧中單個卡的默認樣式。
- cardShadowEnabled - 使用此道具在過渡期間顯示可見陰影。默認為true
cardOverlayEnabled - 使用此prop可在轉換期間顯示可見的堆棧卡覆蓋。默認為false。 - transitionConfig- 返回與默認屏幕轉換合并的對象的函數(在類型定義中查看TransitionConfig )。提供的函數將傳遞以下參數:
- transitionProps - 為新屏幕過渡道具。
- prevTransitionProps - 轉換舊屏幕的道具。
- isModal - 布爾值,指定屏幕是否為模態。
- onTransitionStart - 卡轉換動畫即將開始時要調用的函數。
- onTransitionEnd - 卡過渡動畫完成后要調用的函數。
- transparentCard- 實驗 - 支持將堆棧中的所有卡片保持可見并添加透明背景而不是白色背景。這對于實現模式對話框很有用,其中前一個場景仍應在當前場景下可見。
navigationOptions 用于導航器內的屏幕導航選項
- title - 可用作后備的字符串headerTitle。此外,將用作tabBarLabel(如果嵌套在TabNavigator中)或drawerLabel(如果嵌套在DrawerNavigator中)的后備。
- header - React Element或給定HeaderProps返回React元素的函數,顯示為標題。設置為null隱藏標題。
- headerTitle - 標題使用的字符串,反應元素或反應組件。默認為場景title。當使用的成分,它接收allowFontScaling,style和children道具。傳遞標題字符串children。
- headerBackImage - React Element或Component在標題的后退按鈕中顯示自定義圖像。使用組件時,它在渲染(tintColor,title)時會收到許多道具。默認為帶有react-navigation/views/assets/back-icon.png后方圖像源的圖像組件,后者是平臺的默認后退圖標圖像(iOS上的V形符號和Android上的箭頭)。
- headerRight - React Element顯示在標題的右側。
- headerLeft - React元素或組件顯示在標題的左側。當使用的成分,它接收到一個數道具呈現時(onPress,title,titleStyle和更多-檢查Header.js完整的列表)。
- headerStyle - 標題的樣式對象
- .....還有好多就不一一列舉了,感興趣就去官網看看吧(https://reactnavigation.org/docs/en/stack-navigator.html)
createBottomTabNavigator的使用
屏幕底部的一個簡單標簽欄,可讓您在不同的路線之間切換。路由被懶惰地初始化 - 它們的屏幕組件在首次聚焦之前不會被安裝
API的定義
createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);
RouteConfigs
route configs對象是從路由名稱到路由配置的映射,它告訴導航器為該路由提供什么,請參閱堆棧導航器中的示例。
BottomTabNavigatorConfig
- initialRouteName - 首次加載時初始制表符路徑的routeName。
- order - routeNames數組,用于定義選項卡的順序。
- paths - 提供routeName到path config的映射,該映射覆蓋routeConfigs中設置的路徑。
- backBehavior - 后退按鈕是否會導致選項卡切換到初始選項卡?如果是,則設置為initialRoute,否則none。默認為initialRoute行為。
- tabBarComponent - 可選,覆蓋用作標簽欄的組件。
- tabBarOptions - 具有以下屬性的對象:
- activeTintColor - 活動選項卡的標簽和圖標顏色。
- activeBackgroundColor - 活動選項卡的背景顏色。
- inactiveTintColor - 非活動選項卡的標簽和圖標顏色。
- inactiveBackgroundColor - 非活動選項卡的背景顏色。
- showLabel - 是否為標簽顯示標簽,默認為true。
- showIcon - 是否顯示選項卡的圖標,默認為true。
- style - 標簽欄的樣式對象。
-labelStyle - 選項卡標簽的樣式對象。 - tabStyle - 選項卡的樣式對象。
-allowFontScaling - 標簽字體是否應縮放以符合“文本大小”輔助功能設置,默認為true。 - safeAreaInset- 覆蓋forceInset道具<SafeAreaView>。默認為{ bottom: 'always', top: 'never' }。可用鍵top | bottom | left | right隨值提供'always' | 'never'。
tabBarOptions: {
activeTintColor: '#e91e63',
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: 'blue',
},
}
navigationOptions 用于導航器內的屏幕導航選項
- title - 通用標題可以用作備用headerTitle和tabBarLabel。
- tabBarVisible - true或false顯示或隱藏標簽欄,如果未設置則默認為true。
- tabBarIcon - React Element或給定{ focused: boolean, horizontal: boolean, tintColor: string }返回React.Node 的函數,以顯示在選項卡欄中。horizontal是true當設備處于風景和false肖像時。每當設備方向改變時,都會重新呈現圖標。
- tabBarLabel - 標簽欄或React元素中顯示的選項卡的標題字符串或給定的函數{ focused: boolean, tintColor: string }返回React.Node,以顯示在選項卡欄中。未定義時,使用場景title。要隱藏,請參閱tabBarOptions.showLabel上一節。
- tabBarButtonComponent - 包含圖標,標簽和實現的React Component onPress。默認值是一個包裝器TouchableWithoutFeedback,使其行為與其他觸摸器相同。tabBarButtonComponent: TouchableOpacity會TouchableOpacity改用。
- .....還有好多就不一一列舉了,感興趣就去官網看看吧(https://reactnavigation.org/docs/en/bottom-tab-navigator.html)
實戰部分
基于react-navigation3.0最新的版本實現stack in tabs 和stack over tabs 兩種效果
Stack in tabs
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {
createStackNavigator,
createBottomTabNavigator,
createAppContainer,
createMaterialTopTabNavigator,
} from 'react-navigation'
import { HomeTab, FindTab } from './Router/routers'
const CreateTab = createMaterialTopTabNavigator({
Home: {
screen: HomeTab,
navigationOptions: () => ({
tabBarLabel: '首頁',
})
},
Find: {
screen: FindTab,
navigationOptions: () => ({
tabBarLabel: '發現',
})
}
}, {
initialRouteName: 'Find',
tabBarPosition: 'bottom',
lazy: true,
swipeEnabled: false,
tabBarOptions: {
activeTintColor: 'red',
style: {
backgroundColor: '#fff',
},
}
})
const CreaterTab = createAppContainer(CreateTab)
export default class App extends Component {
render() {
return (
<CreaterTab />
);
}
}
Stack over tabs
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {
createStackNavigator,
createBottomTabNavigator,
createAppContainer,
createMaterialTopTabNavigator,
} from 'react-navigation'
import { HomeTab, FindTab } from './Router/routers'
import WebScreen from './screen/web/webScreen'
const CreateTab = createMaterialTopTabNavigator({
Home: {
screen: HomeTab,
navigationOptions: () => ({
tabBarLabel: '首頁',
})
},
Find: {
screen: FindTab,
navigationOptions: () => ({
tabBarLabel: '發現',
})
}
}, {
initialRouteName: 'Find',
tabBarPosition: 'bottom',
lazy: true,
swipeEnabled: true,
tabBarOptions: {
activeTintColor: 'red',
style: {
backgroundColor: '#fff',
},
}
})
const StacksOverTabs = createStackNavigator({
Root: {
screen: CreateTab,
navigationOptions: {
header: () => null,
}
},
WebView: {
screen: WebScreen,
navigationOptions: {
title: '熊孩寶測試',
},
}
});
const StacksOverTab = createAppContainer(StacksOverTabs)
export default class App extends Component {
render() {
return (
<StacksOverTab />
);
}
}