背景
- 最近把之前的RN專案更新了,react-native升級到了0.58,react-navigation升級到了3.3.0。
- 我們專案結構是TabNavigation,有A/B/C三個Tab,根據使用者的許可權來決定展示幾個Tab,會有四種情況,ABC、AC、BC、C(C是一直存在的)。用createAppContainer建立了四個TabNavigation
升級
- 按照舊版本的實現,建立三個StackNavigator,按照許可權再建立四個TabNavigator,根據許可權來決定展示哪個。新版本升級後,統一使用createXXXNavigator生成,然後通過createAppContainer匯出才行。
遇到的問題
- 修改為新版本的寫法後,發現進入二級頁面tabbar不隱藏了,之前的引數不管用了。查閱文件後,官方給出了建議的寫法:把TabNavigator當做StackNavigator的一部分,push時二級頁面整個蓋到TabNavigator上。reactnavigation.org/docs/en/nav…
- 之前跳轉二級頁面時寫的是this.props.navigation.navigate('XXX'),按照上面官方建議修改之後發現不好使了…原因是this.props.navigation獲取到的是當前頁面的navigation,但是我們外面包了一層TabNavigator,此時應該用TabNavigator的navigation去navigate('XXX')。比如頁面A和頁面B,在TabC上,在頁面A上navigate('D'),但是頁面A的StackNavigator裡沒有D哇,並且我們要把Tab蓋住哇,所以要用TabC的this.props.navigation去navigate('D')才可以。如果頁面A的StackNavigator裡有D,navigate時tabbar還會在,隱藏不了,就又回到了上一個問題。我的解決辦法是:在跳轉二級頁面時發個通知,用TabC接收,然後再TabC裡進行頁面跳轉。有點笨,但是想不到其它好辦法了…
- 還有就是安卓物理返回鍵的問題。這個問題真的很尷尬啊,在第一個Tab進二級頁面,按返回鍵可以很棒的返回,然而在第二個和第三個Tab進二級頁面後,按一下返回沒反應,按兩下就直接到第一個Tab了!!!Oh my god~~~~然後找解決方案,官方文件給出了reactnavigation.org/docs/en/cus…,我是想在一個地方寫然後全域性都可用,來來回試了很多次也沒弄好,只能每個頁面都寫了一次,具體實現看下面的程式碼。
具體實現
- 我們專案結構是TabNavigation,有A/B/C三個Tab,根據使用者的許可權來決定展示幾個Tab,會有四種情況,ABC、AC、BC、C(C是一直存在的)。用createAppContainer建立了四個TabNavigation
const ABCTabbar = createBottomTabNavigator({
'ANav': {screen: ANav,},
'BNav': {screen: BNav,},
'CNav': {screen: CNav,},
});
const ACTabbar = createBottomTabNavigator({
'ANav': {screen: ANav,},
'CNav': {screen: CNav,},
});
const BCTabbar = createBottomTabNavigator({
'BNav': {screen: BNav,},
'CNav': {screen: CNav,},
});
const CTabbar = createBottomTabNavigator({
'CNav': {screen: CNav,},
});
const ABCTabNavigator = createAppContainer(ABCTabbar);
const ACTabNavigator = createAppContainer(ACTabbar);
const BCTabNavigator = createAppContainer(BCTabbar);
const CTabNavigator = createAppContainer(CTabbar);
export { ABCTabNavigator, ACTabNavigator, BCTabNavigator, CTabNavigator };
複製程式碼
- 新建MainNavigation.js,在這個檔案裡判斷使用者有哪些許可權,然後展示相應的TabNavigator
class MainNav extends Component {
render() {
if (this.state.permission === 'ABC') {
return (<ABCTabNavigator/>);
} else if (this.state.permission == 'AC') {
return (<ACTabNavigator/>);
} else if (this.state.permission == 'BC') {
return (<BCTabNavigator/>);
} else {
return (<CTabNavigator/>);
}
}
}
複製程式碼
- 在MainNavigation.js裡,生成一個MainNavigation,在入口render裡配置成就OK了
const Main = createStackNavigator({
MainNav: {screen: MainNav},
DPage: {screen: DPage},
});
const MainNavigation = createAppContainer(Main);
export default MainNavigation;
複製程式碼
- 安卓物理返回鍵問題。從網上找了個工具類AndroidBackAction.js,修改了一下
import {BackHandler} from 'react-native';
const handleAndroidBackButton = callback => {
BackHandler.addEventListener('hardwareBackPress', callback);
};
const removeAndroidBackButtonHandler = (callback) => {
BackHandler.removeEventListener('hardwareBackPress', callback);
}
export {handleAndroidBackButton, removeAndroidBackButtonHandler};
複製程式碼
頁面上的實現:
import {handleAndroidBackButton, removeAndroidBackButtonHandler} from '../../Util/AndroidBackAction.js'; // 你自己的路徑
export default class D extends Component {
constructor(props) {
super(props);
handleAndroidBackButton(this.onBackAndroid); // 一定要在這裡寫
}
componentWillUnmount() {
removeAndroidBackButtonHandler(this.onBackAndroid); // 一定要在這裡寫
}
onBackAndroid = () => {
this.props.navigation.goBack();
return true;
};
}
複製程式碼
還有個按兩下退出應用的,我是寫在了入口的地方(就配置的地方),監聽的方式是一樣的,就是onBackAndroid實現不一樣
onBackAndroid = () => {
if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
//最近2秒內按過back鍵,可以退出應用。
return false;
}
this.lastBackPressed = Date.now();
ToastAndroid.show('再按返回退出應用', ToastAndroid.SHORT);
return true;
};
複製程式碼
好啦,大功告成~~~
結束~撒花~~~