【问题标题】:Open a modal over any screen in a tab bottom navigation flow in React Native在 React Native 的选项卡底部导航流程中的任何屏幕上打开模式
【发布时间】:2020-09-18 00:29:11
【问题描述】:

我遇到了反应原生 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;

【问题讨论】:

  • 所以您希望模态显示在其他底部标签页的顶部,而不是作为单独的页面,对吗?比如假设你在家里,那么你想在主页顶部打开模态框吗?
  • 是的,这正是我想做的。
  • 那么你有没有找到任何解决方案,如果有可以分享一下吗?

标签: javascript react-native react-navigation


【解决方案1】:

您需要将其全部包装在 RootNavigator 中:

const RootStack = createStackNavigator();

const RootNavigator = () => {
  return (
    <RootStack.Navigator screenOptions={{ headerShown: false, presentation: 'modal', animationEnabled: false }}>
      <RootStack.Screen name="BottomTabNavigatorScreen" component={TabRoutes}/>
      <RootStack.Screen name="CustomModal" component={CustomModal} options={{ animationEnabled: true }}/>
    </RootStack.Navigator>
  )
}

export default () => {
  return (
    <NavigationContainer>
      <RootNavigator />
    </NavigationContainer>
  );
};

然后您可以在按钮上添加一个tabPress 侦听器以导航到模态,并在组件字段中添加一个placeholder

const placeholder = () => <View />


<Tab.Screen name="NewTransaction" component={placeholder}
    listeners={({ navigation }) => ({
       tabPress: (e) => {
          e.preventDefault();
          navigation.navigate('CustomModal');
       }
    })>
</Tab.Screen>

【讨论】:

    【解决方案2】:

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

    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;
    

    【讨论】:

    • 我测试过,但它不能正常工作,模态没有渲染。带有 tabBarButton 和 tabBarLabel 的 tab.screen 没有显示在我的 tabbottom 上(即使我放了标签),所以我无法点击。
    • 检查你的模态组件,先用简单的模态试试
    • 您的解决方案不起作用
    猜你喜欢
    • 2023-02-10
    • 1970-01-01
    • 2022-12-24
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 2022-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多