react-navigation動態顯示/隱藏底部導航欄

今天在項目中遇到一個問題,使用createBottomTabNavigator和createStackNavigator構建頁面導航。如圖1所示,底部導航欄每一個Tab都是一個stackNavigator,當我點擊圖中GIS地圖時,切換到其他Tab選項後再切換回來發現頁面依然停留在上次點擊GIS地圖頁面且地圖變黑了(圖 2)。爲了解決這個問題,需要確保切換Tab選項時頁面停留在相應stackNavigator的初始頁面,也就是圖1中的頁面。據此,點擊圖1中GIS地圖時需要將底部導航欄隱藏,這樣當我們想切換Tab選項時只能先返回到初始頁面,也就是圖1中的頁面。



觀察createBottomTabNavigator的源碼可以發現this._renderTabBar()就是用來渲染底部導航欄的,點進去發現返回的是一個BottomTabBar組件。

render() {
    const { navigation, renderScene, lazy } = this.props;
    const { routes } = navigation.state;
    const { loaded } = this.state;
    return <View style={styles.container}>
      <View style={styles.pages}>
        {routes.map((route, index) => {
          if (lazy && !loaded.includes(index)) {
            // Don't render a screen if we've never navigated to it
            return null;
          }

          const isFocused = navigation.state.index === index;

          return <ResourceSavingScene key={route.key} style={[StyleSheet.absoluteFill, { opacity: isFocused ? 1 : 0 }]} isVisible={isFocused}>
            {renderScene({ route })}
          </ResourceSavingScene>;
        })}
      </View>
      {this._renderTabBar()}
    </View>;
  }
_renderTabBar = () => {
    const {
      tabBarComponent: TabBarComponent = BottomTabBar,
      tabBarOptions,
      navigation,
      screenProps,
      getLabelText,
      getAccessibilityLabel,
      getButtonComponent,
      getTestID,
      renderIcon,
      onTabPress
    } = this.props;

    const { descriptors } = this.props;
    const { state } = this.props.navigation;
    const route = state.routes[state.index];
    const descriptor = descriptors[route.key];
    const options = descriptor.options;

    if (options.tabBarVisible === false) {
      return null;
    }

    return <TabBarComponent {...tabBarOptions} jumpTo={this._jumpTo} navigation={navigation} screenProps={screenProps} onTabPress={onTabPress} getLabelText={getLabelText} getButtonComponent={getButtonComponent} getAccessibilityLabel={getAccessibilityLabel} getTestID={getTestID} renderIcon={renderIcon} />;
  };

繼續觀察BottomTabBar的源碼發現其根據當前的路由路徑routes渲染一個包含有標籤與圖表的ButtonComponent組件。開啓調試模式觀察routes結構發現,routes是一個json對象,其routes字段爲一個數組,表示當前stackNavigator中的頁面個數,當頁面位於如圖1所示的初始頁面時該數組長度爲1,位於如圖2所示的頁面時該數組長度大於1。

const { routes } = navigation.state;

    const tabBarStyle = [styles.tabBar, this._shouldUseHorizontalLabels() && !Platform.isPad ? styles.tabBarCompact : styles.tabBarRegular, style];
    
    return <SafeAreaView style={tabBarStyle} forceInset={safeAreaInset}>
      {routes.map((route, index) => {
        const focused = index === navigation.state.index;
        const scene = { route, focused };
        const accessibilityLabel = this.props.getAccessibilityLabel({
          route
        });
        const testID = this.props.getTestID({ route });

        const backgroundColor = focused ? activeBackgroundColor : inactiveBackgroundColor;

        const ButtonComponent = this.props.getButtonComponent({ route }) || TouchableWithoutFeedbackWrapper;

        return <ButtonComponent key={route.key} onPress={() => onTabPress({ route })} testID={testID} accessibilityLabel={accessibilityLabel} style={[styles.tab, { backgroundColor }, this._shouldUseHorizontalLabels() ? styles.tabLandscape : styles.tabPortrait, tabStyle]}>
          {this._renderIcon(scene)}
          {this._renderLabel(scene)}
        </ButtonComponent>;
      })}
    </SafeAreaView>;

因此,可以在BottomTabBar組件中進行條件渲染,當頁面處於如圖2所示的頁面時返回一個空的View組件,代碼如下:

//點擊子頁面時隱藏底部導航欄
    let number = 0;
    for (var i = 0; i < routes.length; i++) {
      if (routes[i].routes.length > 1) {
        number = number + 1;
      }
    }
    if (number != 0) {
      return <View style={{
        height: 30,
        backgroundColor: '#FFFFFF'
      }}/>
    }

至此,可以實現點擊GIS地圖時隱藏底部導航欄的功能(圖3)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章