如何从 React 导航 BottomTabNavigator 显示底部 sheet?

How to display a bottom sheet from React navigation BottomTabNavigator?


如何从 React 导航 BottomTabNavigator 显示底部 sheet?

我想在单击 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();中打开一个模态组件

但是有点卡顿,白底0.01秒左右,无法滚动(我不想再用这个方法了)。

您尝试使用 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

 <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 

这是我的解决方案

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>