react native navigation 隱藏 bottomTab

react native navigation 隱藏 bottomTab

前言

在做 react-native app 時, 用到了 react navigation 的 bottom tab navigation, 但是在某些情況下需要控制 bottom tab bar 的顯示和隱藏。

試了很多中方法,最後比較簡單的方式是修改nodeModels裏面的源碼。

本文 react-native 版本爲 0.59.8 , react-navigation 版本爲 3.10.1

開始

核心思想是從 nodemodels 中找到渲染 bottom tab 的代碼,直接的來控制它的顯示隱藏。

找到代碼文件爲 nodemodels的 react-navigation-tabs/src/navigators/createBottomTabNavigator.js

爲該文件中的類添加 state hidden=false;

在該類的 componentDidMount 中, 將hidden值的控制權 掛到 global.func上,

componentDidMount() {
    global.func.showBottomTab = () => {
    this.setState({
        hidden: false
    })
    }
    global.func.hideBottomTab = () => {
    this.setState({
        hidden: true
    })
    }
}

在該類的 render 中, 判斷 this.state.hidden, 若 true, 則直接return ,即可實現隱藏

在需要隱藏 bottom tab 時, 只需要調用 global.func.hideBottom() 即可,項目中任何位置均可調用;

需要顯示時,調用 global.func.showBottom();

文件路徑爲 react-navigation-tabs/src/navigators/createBottomTabNavigator.js,修改後的代碼參考:

/* @flow */

// 使用該文件取覆蓋 nodemodels的 react-navigation-tabs/src/navigators/createBottomTabNavigator.js
/* @flow */

import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import { polyfill } from 'react-lifecycles-compat';

// eslint-disable-next-line import/no-unresolved
import { ScreenContainer } from 'react-native-screens';

import createTabNavigator, {
type InjectedProps,
} from '../utils/createTabNavigator';
import BottomTabBar, { type TabBarOptions } from '../views/BottomTabBar';
import ResourceSavingScene from '../views/ResourceSavingScene';

type Props = InjectedProps & {
getAccessibilityRole: (props: { route: any }) => string,
getAccessibilityStates: (props: { route: any }) => Array<string>,
lazy?: boolean,
tabBarComponent?: React.ComponentType<*>,
tabBarOptions?: TabBarOptions,
};

type State = {
loaded: number[],
};

class TabNavigationView extends React.PureComponent<Props, State> {
static defaultProps = {
    lazy: true,
    getAccessibilityRole: () => 'button',
    getAccessibilityStates: ({ focused }) => (focused ? ['selected'] : []),
};

static getDerivedStateFromProps(nextProps, prevState) {
    const { index } = nextProps.navigation.state;

    return {
    // Set the current tab to be loaded if it was not loaded before
    loaded: prevState.loaded.includes(index)
        ? prevState.loaded
        : [...prevState.loaded, index],
    };
}

state = {
    loaded: [this.props.navigation.state.index],
    hidden: false
};

_renderTabBar = () => {
    const {
    tabBarComponent: TabBarComponent = BottomTabBar,
    tabBarOptions,
    navigation,
    screenProps,
    getLabelText,
    getAccessibilityLabel,
    getButtonComponent,
    getAccessibilityRole,
    getAccessibilityStates,
    getTestID,
    renderIcon,
    onTabPress,
    onTabLongPress,
    } = 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}
        onTabLongPress={onTabLongPress}
        getLabelText={getLabelText}
        getButtonComponent={getButtonComponent}
        getAccessibilityLabel={getAccessibilityLabel}
        getAccessibilityRole={getAccessibilityRole}
        getAccessibilityStates={getAccessibilityStates}
        getTestID={getTestID}
        renderIcon={renderIcon}
    />
    );
};

_jumpTo = (key: string) => {
    const { navigation, onIndexChange } = this.props;

    const index = navigation.state.routes.findIndex(route => route.key === key);

    onIndexChange(index);
};

componentDidMount() {
    global.func.showBottomTab = () => {
    this.setState({
        hidden: false
    })
    }
    global.func.hideBottomTab = () => {
    this.setState({
        hidden: true
    })
    }
}


render() {
    const { navigation, renderScene, lazy } = this.props;
    const { routes } = navigation.state;
    const { loaded } = this.state;


    let tabBar = this._renderTabBar()
    if (this.state.hidden) {
    tabBar = <View></View>
    }

    return (
    <View style={styles.container}>
        <ScreenContainer 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}
                isVisible={isFocused}
            >
                {renderScene({ route })}
            </ResourceSavingScene>
            );
        })}
        </ScreenContainer>
        {tabBar}
    </View>
    );
}
}

polyfill(TabNavigationView);

const styles = StyleSheet.create({
container: {
    flex: 1,
    overflow: 'hidden',
},
pages: {
    flex: 1,
},
});

export default createTabNavigator(TabNavigationView);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章