如何从 React 导航 BottomTabNavigator 显示底部工作表?

Posted

技术标签:

【中文标题】如何从 React 导航 BottomTabNavigator 显示底部工作表?【英文标题】:How to display a bottom sheet from React navigation BottomTabNavigator? 【发布时间】:2022-01-18 13:06:34 【问题描述】:

My solution


如何在 React 导航 BottomTabNavigator 中显示底部工作表?

当我点击tabBarIcon(可能是图片中添加按钮)而不是组件时,我想显示reanimated-bottom-sheet。

我正在使用

<Tab.Screen
    name=Name.name_add_application
    component=Add
    options=
      tabBarIcon: (focused) => (
        <Image source=TK_Add resizeMode="contain" style=styles.addBtn />
      ),
      tabBarButton: props => <CustomTabButton ...props />,
    
    listeners=(navigation) => (
      tabPress: e => 
        e.preventDefault();
        navigation.navigate('CreateNew');
      ,
    )
  />

const Tab = createBottomTabNavigator();

<MainStack.Group
  screenOptions=
    headerShown: false,
    cardStyle: backgroundColor: 'rgba(0, 0, 0, 0)',
    cardOverlayEnabled: true,
    cardStyleInterpolator: (current: progress) => (
      cardStyle: 
        opacity: progress.interpolate(
          inputRange: [0, 0.5, 0.9, 1],
          outputRange: [0, 0.25, 0.7, 1],
        ),
      ,
      overlayStyle: 
        opacity: progress.interpolate(
          inputRange: [0, 0.5],
          outputRange: [0, 0.25],
          extrapolate: 'clamp',
        ),
      ,
    ),
  
  mode="modal">
  <MainStack.Screen
    name="CreateNew"
    component=CreateNew
    options=
      animationEnabled: true,
      presentation: 'transparentModal',
    
  />
</MainStack.Group>

const MainStack = createStackNavigator(); 中打开一个Modal 组件

但是有点卡顿,显示白色背景约0.01s不能滚动(我不想再用这个方法了)。

【问题讨论】:

【参考方案1】:

您是否尝试使用the custom tabBar props?

这是一个例子:

<Tab.Navigator
  tabBar=() => <BottomSheet />
  screenOptions= headerShown: false 
>
    <Tab.Screen name=... component=... />
    <Tab.Screen name=... component=... />
    <Tab.Screen name=... component=... />
</Tab.Navigator

从文件夹的角度来看,你会有这样的东西

./src/navigators/
  ├──bottom-tabs-navigator.tsx
  └──bottom-sheet/
      ├──bottom-sheet.tsx
      └──bottom-tab-bar.tsx

【讨论】:

谢谢你。我会试试的。【参考方案2】:
 <Tab.Screen
    name=translations.logout
    component=HomeScreen
    options=
      tabBarLabel: translations.logout,
      tabBarActiveTintColor: appTheme.themeColor,
      headerTitleAlign: 'center',
      headerStyle:height: headerHeight,
      tabBarLabelStyle:  fontSize: 14 ,
      tabBarIcon: () => (
        <Image source=AppImages.settings style=CommonStyle.tabBarImage />
      ),
    
    listeners=
      tabPress: (e) => 
        showLogoutAlert();
        e.preventDefault();
      ,
    
  />
 e.preventDefault(); will prevent from tapping 

【讨论】:

谢谢你。但我明白了。【参考方案3】:

这是我的解决方案

function MyTabBar( state, descriptors, navigation ) 
  const tabRef = React.createRef();
  const fall = new Animated.Value(1);

  const renderInner = () => (
    <View style=styles.panel>/* ButtomSheet body */</View>
  );

  const renderHeader = () => (
    <View style=styles.header>/* ButtomSheet header */</View>
  );

  return (
    <View style= flexDirection: "row" >
      <BottomSheet
        ref=tabRef
        snapPoints=[CONST.HEIGHT * 0.5, 0]
        renderContent=renderInner
        renderHeader=renderHeader
        initialSnap=1
        callbackNode=fall
        enabledGestureInteraction=true
      />
      state.routes.map((route, index) => 
        const  options  = descriptors[route.key];
        // const label =
        //   options.tabBarLabel !== undefined
        //     ? options.tabBarLabel
        //     : options.title !== undefined
        //     ? options.title
        //     : route.name;

        const isFocused = state.index === index;

        const onPress = () => 
          switch (index) 
            // add button's case ( which I want to show bottom sheet)
            case 2:
              tabRef.current.snapTo(0);
              break;

            default:
              const event = navigation.emit(
                type: "tabPress",
                target: route.key,
              );

              if (!isFocused && !event.defaultPrevented) 
                navigation.navigate(route.name);
              
              break;
          
        ;

        const onLongPress = () => 
          navigation.emit(
            type: "tabLongPress",
            target: route.key,
          );
        ;

        const TabIcon = () => 
          // custom your tab
        ;

        return (
          <Pressable
            accessibilityRole="button"
            accessibilityState=isFocused ?  selected: true  : 
            accessibilityLabel=options.tabBarAccessibilityLabel
            testID=options.tabBarTestID
            onPress=onPress
            onLongPress=onLongPress
            style=
              flex: 1,
              alignItems: "center",
              backgroundColor: "#fff",
            
          >
            <TabIcon />
            /* label */
          </Pressable>
        );
      )
    </View>
  );

const Tab = createBottomTabNavigator();

<Tab.Navigator
  tabBar=props => <MyTabBar ...props />
  screenOptions=headerShown: false>
  <Tab.Screen name=/* screen name */ component=/* compo */ />
  /* more screens */
</Tab.Navigator>

【讨论】:

以上是关于如何从 React 导航 BottomTabNavigator 显示底部工作表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React js 中从一个页面导航到另一个页面?

在带有 react-router 的 React 中,当我从一个复杂的视图中导航出来,然后直接返回时,如何保留一个人的所有视图选择?

React-native-splashscreen 和导航

如何通过 React Navigation 将导航道具传入功能组件屏幕?

如何在 react-native 中的 mapbox 地图上绘制导航线?

如何修复反应导航从屏幕顶部移动我的组件?