React-Navigation 入門到高階使用
對(duì)于新手入坑React-Native,可能搭建項(xiàng)目沒有好用的腳手架會(huì)浪費(fèi)很多的時(shí)間在查找,嘗試和驗(yàn)證,例如react-navigation,必備但是又不需要精研的組件,那么接下來你想要的都會(huì)有:
React-Navigation 官網(wǎng)直通車,對(duì)于新手使用,我只說關(guān)鍵的地方
話不多說,在你的項(xiàng)目里install package
npm install react-navigation
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
在強(qiáng)調(diào)一次,React-Native版本>= 0.60 會(huì)自動(dòng)linking,
否則需要你手動(dòng)去linking,官網(wǎng)都有說明:
React-Native >= 0.60
cd ios
pod install
React-Native < 0.60, 還需要:
react-native link react-native-reanimated
react-native link react-native-gesture-handler
react-native link react-native-screens
react-native link react-native-safe-area-context
下面的圖你會(huì)看到auto-lingk...

當(dāng)然針對(duì)你的項(xiàng)目andoridx,你還需要jetifier
npm install --save-dev jetifier
在package.json中
"scripts": {
"postinstall": "jetifier -r"
}
默認(rèn)你的React-Native已經(jīng)升級(jí)0.60及以上,運(yùn)行腳本
npm run postinstall
在MainActivity.java中
package com.reactnavigation.example;
import com.facebook.react.ReactActivity;
+ import com.facebook.react.ReactActivityDelegate;
+ import com.facebook.react.ReactRootView;
+ import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
public class MainActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "Example";
}
+ @Override
+ protected ReactActivityDelegate createReactActivityDelegate() {
+ return new ReactActivityDelegate(this, getMainComponentName()) {
+ @Override
+ protected ReactRootView createRootView() {
+ return new RNGestureHandlerEnabledRootView(MainActivity.this);
+ }
+ };
+ }
}
在使用的地方(app.js或index.js)引入頭文件即可
import 'react-native-gesture-handler';
那現(xiàn)在準(zhǔn)備工作已經(jīng)OK了,其實(shí)準(zhǔn)備工作和官網(wǎng)無差別,接下來是如何無銜接的使用stackNavigator和BottomTabNavigator。

官網(wǎng)中說createBottomTabNavigator有routes和config,
- routes是設(shè)置單一界面,里面的navigationOptions設(shè)置的是tabBar的所有屬性:如title,tabBarIcon,tabBarIcon,tabBarOnPress...等等。
tabBarIcon中自有:
{ focused: boolean, horizontal: boolean, tintColor: string }
focused: 是否被選擇
horizontal:是否旋轉(zhuǎn)手機(jī)
tintColor:選擇的顏色
tabBarOnPress當(dāng)tabBar選擇要繼承defaultHandler,否則會(huì)無效:
({navigation, defaultHandler}) => {
defaultHandler()
},
- config是tabBar的統(tǒng)一設(shè)置,如initialRouteName,初始加載route,tabBarOptions設(shè)置的一些屬性,官網(wǎng)都有說明,簡(jiǎn)單說幾個(gè)常用的:activeTintColor,被點(diǎn)擊的顏色;labelStyle,名稱設(shè)置;style:tabBar約束設(shè)置。
具體使用如下:
const tabNavigator = createBottomTabNavigator(
{
Home: {
screen: TTHomeScreen,
navigationOptions: {
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? require('../image/home.png') : require('../image/unHome.png')}
style={{width: 25, height: 25}}/>
),
tabBarOnPress: ({navigation, defaultHandler}) => {
defaultHandler()
console.log(navigation.state.routeName)
},
}
},
Car: {
screen: TTCarScreen,
navigationOptions: {
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? require('../image/car.png') : require('../image/unCar.png')}
style={{width: 25, height: 25}}/>
),
tabBarOnPress: ({navigation, defaultHandler}) => {
defaultHandler()
console.log(navigation.state.routeName)
}
}
},
Mine: {
screen: TTMineScreen,
navigationOptions: {
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? require('../image/mine.png') : require('../image/unMine.png')}
style={{width: 25, height: 25}}/>
),
tabBarOnPress: ({navigation, defaultHandler}) => {
defaultHandler()
console.log(navigation.state.routeName)
}
}
},
Settings: {
screen: TTSettingScreen,
navigationOptions: {
tabBarIcon: ({focused, tintColor}) => (
<Image source={focused ? require('../image/set.png') : require('../image/unSet.png')}
style={{width: 25, height: 25}}/>
),
tabBarOnPress: ({navigation, defaultHandler}) => {
defaultHandler()
console.log(navigation.state.routeName)
},
}
}
},
{
/* Other configuration remains unchanged */
tabBarOptions: {
activeTintColor: '#e91e63',
labelStyle: {
fontSize: 14,
},
style: {
backgroundColor: 'white',
},
},
}
);
設(shè)置完這些你會(huì)發(fā)現(xiàn),缺少設(shè)置stackNavitor,也沒有跳轉(zhuǎn)路由,
先來設(shè)置路由類
創(chuàng)建一個(gè)新的類TTStackRouter
const NavigatorScreen = {
TTHomeDetailScreen: {
screen: TTHomeDetailScreen,
navigationOptions:{
title: '詳情'
}
},
<!--可以添加更多的跳轉(zhuǎn)類,如TTHomeDetailScreen-->
}
export default NavigatorScreen;
把剛剛的tabNavigator添加進(jìn)來,
屬性設(shè)置在項(xiàng)目中自行參考是否需要
<!--navigator設(shè)置后面都有具體描述可以參考-->
NavigatorScreen.mainScreen = {
screen: tabNavigator,
navigationOptions: {
// headerShown: false, // 隱藏header
headerStyle: {
elevation: 0, // 移除 Android Header 陰影
shadowOpacity: 0, // 移除 iOS Header 陰影
},
headerTitleAlign: 'center', // Android 標(biāo)題居中
headerBackTitleVisible: false, // 隱藏 iOS 返回按鈕標(biāo)題
headerPressColorAndroid: 'transparent', // 移除 Android 點(diǎn)擊返回按鈕效果
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, // 切換路由時(shí)水平動(dòng)畫
headerStyleInterpolator: HeaderStyleInterpolators.forUIKit, // 切換路時(shí) Header 動(dòng)畫
},
};
路由配置好了,使用的時(shí)候會(huì)發(fā)現(xiàn),navigator的routerName都是mainScreen,現(xiàn)在去為每個(gè)模塊配置routerName
// 給tabNavigator添加headerTitle
tabNavigator.navigationOptions = ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
// You can do whatever you like here to pick the title based on the route name
const headerTitle = routeName;
return {
headerTitle,
};
};
最后配置stackNavigator,并輸出creatAppContainer,到現(xiàn)在完成了react-navigation的簡(jiǎn)單項(xiàng)目配置
const mainScreenStack = createStackNavigator(NavigatorScreen, {
initialRouteName: 'mainScreen',
defaultNavigationOptions: {
headerBackTitleVisible: false, // 隱藏 iOS 返回按鈕標(biāo)題
}
});
const AppContainer = createAppContainer(mainScreenStack);
export default AppContainer;