首页 > 解决方案 > 在 React Native 的选项卡底部导航流程中的任何屏幕上打开模式

问题描述

我正面临反应原生 tabBottom 导航的问题。我有一个 TabButton 自定义组件,在单击时会呈现模态,但我似乎找不到在其他选项卡上呈现特定模态的方法,而不仅仅是呈现为孤立的组件。

我想要实现的是,当我单击黄色按钮时,它会呈现模态,但是(主页、帮助、调整和图形)之类的选项卡就像模态的背景一样,而不仅仅是在另一个组件中呈现模态。

我定制的 TabButton 组件:

import React from 'react';
import {TouchableWithoutFeedback} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Button from './styles';

const TabButton = ({onPress, focused}) => {
  return (
    <TouchableWithoutFeedback onPress={onPress}>
      <Button focused={focused}>
        <Icon name="add" size={35} color={'white'} />
      </Button>
    </TouchableWithoutFeedback>
  );
};

export default TabButton;

选项卡按钮

我的 tab.routes.js:

import React from 'react';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import TabButton from '../components/Tab/Button';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Home from '../containers/Home';
import Graphic from '../containers/Graphic';
import Help from '../containers/Help';
import NewTransaction from '../containers/NewTransaction';
import SettingsStack from './settings.routes';

const icons = {
  Home: {
    name: 'home',
  },
  Graphic: {
    name: 'pie-chart',
  },
  NewTransaction: {
    name: 'notifications-none',
  },
  Help: {
    name: 'help-outline',
  },
  Adjustment: {
    name: 'settings',
  },
};

const Tab = createBottomTabNavigator();
const TabRoutes = () => (
  <Tab.Navigator
    initialRouteName="HomeScreen"
    screenOptions={({route, navigation}) => ({
      tabBarIcon: ({color, size, focused}) => {
        if (route.name === 'NewTransaction') {
          return <TabButton focused={focused} onPress={() => navigation.navigate('NewTransaction')} />;
        }
        const {name} = icons[route.name];
        return <Icon name={name} size={size} color={color} />;
      },
    })}
    tabBarOptions={{
      keyboardHidesTabBar: true,
      activeTintColor: '#f8b006',
      inactiveTintColor: '#1C3041',
      style: {
        height: 60,
      },
      iconStyle: {
        marginTop: 5,
      },
      labelStyle: {
        fontSize: 12,
        marginBottom: 10,
      },
    }}>
    <Tab.Screen
      options={{
        title: 'Home',
      }}
      name="Home"
      component={Home}
    />
    <Tab.Screen
      options={{
        title: 'Gráfico',
      }}
      name="Graphic"
      component={Graphic}
    />
    <Tab.Screen
      options={{
        title: '',
      }}
      component={NewTransaction}
      name="NewTransaction"/>
    <Tab.Screen
      options={{
        title: 'Ajuda',
      }}
      name="Help"
      component={Help}
    />
    <Tab.Screen
      options={{
        title: 'Ajustes',
      }}
      name="Adjustment"
      component={SettingsStack}
    />
  </Tab.Navigator>
);

export default TabRoutes;

我的模态组件:

import React from 'react';
import RBSheet from 'react-native-raw-bottom-sheet';
import PropTypes from 'prop-types';

const CustomModal = ({children, refRBSheet, borderRadius, height, animationType, onClose, onOpen}) => {
  return (
    <RBSheet
      animationType={animationType}
      height={height}
      onClose={onClose}
      onOpen={onOpen}
      ref={refRBSheet}
      closeOnDragDown={true}
      closeOnPressMask={true}
      customStyles={{
        container: {
          backgroundColor: 'white',
          borderTopLeftRadius: borderRadius,
          borderTopRightRadius: borderRadius,
        },
      }}>
      {children}
    </RBSheet>
  );
};

export default CustomModal;

以及呈现模态的我的 NewTransaction 组件:

import React, {useRef, useEffect} from 'react';
import {Text, View} from 'react-native';
import CustomModal from '../../components/Modal/';
const NewTransaction = ({isVisible, onClose}) => {
  const refRBSheet = useRef();

  useEffect(() => {
    if (isVisible) {
      refRBSheet.current.open();
    } else {
      refRBSheet.current.close();
    }
  }, [isVisible]);

  return (
    <CustomModal refRBSheet={refRBSheet} onClose={onClose}>
      <View>
        <Text>Hellow</Text>
      </View>
    </CustomModal>
  );
};

export default NewTransaction;

标签: javascriptreact-nativereact-navigation

解决方案


首先,创建一个返回 null 的新页面/屏幕,以便在启动模式时它不会显示任何背景。像这样

const MyModalBackgroundScreen = () => {
  return null;
};

之后在选项卡导航器中创建选项卡

import React from 'react';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import TabButton from '../components/Tab/Button';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Home from '../containers/Home';
import Graphic from '../containers/Graphic';
import Help from '../containers/Help';
import NewTransaction from '../containers/NewTransaction';
import SettingsStack from './settings.routes';

const icons = {
  Home: {
    name: 'home',
  },
  Graphic: {
    name: 'pie-chart',
  },
  NewTransaction: {
    name: 'notifications-none',
  },
  Help: {
    name: 'help-outline',
  },
  Adjustment: {
    name: 'settings',
  },
};

const Tab = createBottomTabNavigator();
const TabRoutes = () => (
  <Tab.Navigator
    initialRouteName="HomeScreen"
    screenOptions={({route, navigation}) => ({
      tabBarIcon: ({color, size, focused}) => {
        //removd that if condition 
        const {name} = icons[route.name];
        return <Icon name={name} size={size} color={color} />;
      },
    })}
    tabBarOptions={{
      keyboardHidesTabBar: true,
      activeTintColor: '#f8b006',
      inactiveTintColor: '#1C3041',
      style: {
        height: 60,
      },
      iconStyle: {
        marginTop: 5,
      },
      labelStyle: {
        fontSize: 12,
        marginBottom: 10,
      },
    }}>
    <Tab.Screen
      options={{
        title: 'Home',
      }}
      name="Home"
      component={Home}
    />
    <Tab.Screen
      options={{
        title: 'Gráfico',
      }}
      name="Graphic"
      component={Graphic}
    />
    <Tab.Screen
      name="Graphic"
      component={MyModalBackgroundScreen} //first import this in this 
      options={{
        tabBarLabel: ({}) => {
          return null; //no label will be displayed
        },
        tabBarButton: () => {
          return <CustomModal refRBSheet={refRBSheet} onClose={onClose}>; // call your modal here directly.
        },
      }}
    />
    <Tab.Screen
      options={{
        title: '',
      }}
      component={NewTransaction}
      name="NewTransaction"/>
    <Tab.Screen
      options={{
        title: 'Ajuda',
      }}
      name="Help"
      component={Help}
    />
    <Tab.Screen
      options={{
        title: 'Ajustes',
      }}
      name="Adjustment"
      component={SettingsStack}
    />
  </Tab.Navigator>
);

export default TabRoutes;

推荐阅读