前面我們學(xué)習(xí)了React Native常見的組件的屬性和方法,以及簡單的應(yīng)用绢彤,那我們接下來學(xué)習(xí)一下常用的第三方的組件描馅,第一個就是navigation和TabBar营勤。
一.導(dǎo)入
npm install react-navigation --save
二.簡介
react-navigation主要包括導(dǎo)航富弦,底部tab沟娱,頂部tab,側(cè)滑等腕柜,功能很強大济似,而且體驗接近原生矫废。今天我們介紹的組件分別為:
- 導(dǎo)航 -> StackNavigator
- 底部或者頂部tab -> TabNavigator
- 側(cè)滑 -> DrawerNavigator
(一).StackNavigator
基礎(chǔ)用法/屬性介紹
const MyApp = StackNavigator({
// 對應(yīng)界面名稱
MyTab: { screen: MyTab, },
Detail: { screen: Detail, navigationOptions:{ headerTitle:'詳情', headerBackTitle:null, } },
},
{ headerMode: 'screen', });
導(dǎo)航配置
- screen:對應(yīng)界面名稱,需要填入import之后的頁面砰蠢。
- navigationOptions:配置StackNavigator的一些屬性蓖扑。
- title:標(biāo)題,如果設(shè)置了這個導(dǎo)航欄和標(biāo)簽欄的title就會變成一樣的娩脾,所以不推薦使用這個方法赵誓。
- header:可以設(shè)置一些導(dǎo)航的屬性,當(dāng)然如果想隱藏頂部導(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)改成"返回"椿肩。(上個頁面的標(biāo)題過長瞻颂,導(dǎo)致顯示不下,所以改成了短一些的郑象。)
- headerRight:設(shè)置導(dǎo)航條右側(cè)贡这。可以是按鈕或者其他厂榛。
- headerLeft:設(shè)置導(dǎo)航條左側(cè)盖矫。可以是按鈕或者其他击奶。
- headerStyle:設(shè)置導(dǎo)航條的樣式辈双。背景色,寬高等柜砾。如果想去掉安卓導(dǎo)航條底部陰影可以添加elevation: 0湃望,iOS下用shadowOpacity: 0。
- headerTitleStyle:設(shè)置導(dǎo)航條文字樣式痰驱。安卓上如果要設(shè)置文字居中证芭,只要添加alignSelf:'center'就可以了
- headerBackTitleStyle:設(shè)置導(dǎo)航條返回文字樣式。
- headerTintColor:設(shè)置導(dǎo)航欄文字顏色萄唇¢菡剩總感覺和上面重疊了。
- headerPressColorAndroid:安卓獨有的設(shè)置顏色紋理另萤,需要安卓版本大于5.0
- gesturesEnabled:是否支持滑動返回收拾湃密,iOS默認(rèn)支持诅挑,安卓默認(rèn)關(guān)閉
導(dǎo)航視覺效果 - 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并進入指定頁面。path屬性用于聲明一個界面路徑吱瘩,例如:【/pages/Home】道伟。此時我們可以在手機瀏覽器中輸入:app名稱://pages/Home來啟動該App,并進入Home界面搅裙。
Demo
組件注冊
const Navigator = StackNavigator(
{ Login: {screen: Login},
ForgotPassword: {screen: ForgotPassword, navigationOptions: {header: null,}},
CodeLogin: {screen: CodeLogin}, }, { navigationOptions: { headerStyle: {backgroundColor: color.theme}, headerBackTitle: null, headerTintColor: '#ffffff', showIcon: true, },
transitionConfig: TransitionConfiguration,
headerMode: 'screen', // 導(dǎo)航欄的顯示模式, screen: 有漸變透明效果, float: 無透明效果, none: 隱藏導(dǎo)航欄 }
);
動畫切換
const TransitionConfiguration = () => ({
screenInterpolator: (sceneProps) => { const {scene} = sceneProps;
const {route} = scene; const params = route.params || {};
const transition = params.transition || 'forHorizontal';
return CardStackStyleInterpolator[transition](sceneProps); },
});
Model彈出
const {navigate} = this.props.navigation;
navigate('CodeLogin', {transition: 'forVertical'});
參數(shù)傳遞
const {navigate} = this.props.navigation;
navigate('CodeLogin', {phone: this.state.phone});
讀取參數(shù)
phone=this.props.navigation.state.params.phone,
函數(shù)傳遞
navigate('CodeLogin', { setPictureData: this.setPictureData.bind(this) });
函數(shù)調(diào)用
this.props.navigation.state.params.setPictureData(data.path)
重置路由切換導(dǎo)航控制器
this.props.navigation.dispatch(resetAction)})
切換到Main頁面
const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'Main'}) ] })
關(guān)于goBack返回指定頁面
react-navigation是提供了goBack()到指定頁面的方法的皱卓,那就是在goBack()中添加一個參數(shù),但當(dāng)你使用goBack('Main')的時候部逮,你會發(fā)現(xiàn)并沒有跳轉(zhuǎn)娜汁,原因是react-navigation默認(rèn)goBack()中的參數(shù)是系統(tǒng)隨機分配的key,而不是手動設(shè)置的routeName兄朋,而方法內(nèi)部又沒有提供可以獲得key的方法掐禁,所以這里只能通過修改源碼將key換成routeName了。
下面的內(nèi)容直接引用了hello老文的內(nèi)容
把項目/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()方法沒反應(yīng)了, 必須加個null進去, 寫成goBack(null)...
關(guān)于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,
};
}
}
關(guān)于快速點擊會導(dǎo)致多次跳轉(zhuǎn)的問題解決辦法
修改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"