使用持久性操作表呈现底部选项卡

Render bottom tab with persistent action sheet

提问人:Walter Monecke 提问时间:11/8/2023 最后编辑:Walter Monecke 更新时间:11/16/2023 访问量:141

问:

我正在尝试在我的应用程序中实现以下布局:

enter image description here

基本上将我的内容呈现在底部工作表内,而地图始终呈现为后面的屏幕。当您四处走动时,底部工作表会保持不变,但内容会发生变化。<BottomTabNavigator/>

我正在使用 react-navigation@gorhom/bottom-sheet

我能够实现这一点,但需要一些有关如何使用 react-navigation 正确设置它的指导。

我还没有找到官方指南或任何东西,所以我在网上查找,有些人提到创建一个自定义标签栏,在顶部呈现一个 BottomSheet(这就是我能够实现这种布局的方式)。像这样的东西:

const CustomTabBar = props => {
  return (
    <React.Fragment>
       <BottomSheet
         snapPoints = {[450, 300, 0]}
         renderContent = {this.renderInner}
         renderHeader = {this.renderHeader}
       />
      <BottomTabBar {...props} />
    </React.Fragment>
  );
};

然后,我会在模态中进行条件渲染以显示不同的屏幕。这确实感觉有点骇人听闻,输入导航和状态道具是一场噩梦。

有没有更好的方法可以做到这一点?

我试过把我的包裹在里面,但这似乎不起作用。<BottomTab /><BottomSheet />

自定义选项卡栏是执行此操作的正确方法吗?

任何帮助都非常感谢!

react-native react-navigation 反应原生导航

评论

0赞 Vicky Ahuja 11/10/2023
您想在所有选项卡中显示此底部工作表还是仅在特定选项卡内显示此底部工作表?
0赞 Walter Monecke 11/10/2023
所有标签!@VickyAhuja 与iOS的FindMy应用程序基本相同
0赞 Vicky Ahuja 11/13/2023
我想不应该通过添加底部表来使底部标签栏变得沉重,相反,我们应该把它放在我们的屏幕中,我们可以拥有可重用的组件,这样我们就可以在屏幕内用最少的代码重用。
0赞 Walter Monecke 11/14/2023
我的意思是底部工作表的逻辑只是渲染差异屏幕。它的“沉重”不应该影响性能。

答:

1赞 Vicky Ahuja 11/16/2023 #1

由于此处自定义选项卡栏具有底部工作表,因此所有选项卡屏幕都是相同的,如果我们在自定义底部选项卡组件中管理底部工作表状态,也可能会出现性能问题。

尝试使用以下示例来实现与上图所示相同的功能。

import React, {
  forwardRef,
  useEffect,
  useImperativeHandle,
  useMemo,
  useRef,
} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import BottomSheet from '@gorhom/bottom-sheet';
import {GestureHandlerRootView} from 'react-native-gesture-handler';

import {SafeAreaProvider} from 'react-native-safe-area-context';

import {NavigationContainer} from '@react-navigation/native';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

const BottomTab = createBottomTabNavigator();

const CustomBottomSheet = forwardRef((myProps, ref) => {
  // ref
  const bottomSheetRef = useRef<BottomSheet>(null);

  // variables
  const snapPoints = useMemo(() => ['25%'], []);

  useImperativeHandle(
    ref,
    () => {
      return {
        open: () => {
          bottomSheetRef.current?.expand();
        },
        close: () => {
          bottomSheetRef.current?.close();
        },
      };
    },
    [],
  );

  return (
    <BottomSheet ref={bottomSheetRef} snapPoints={snapPoints}>
      <View style={styles.centeredContent}>
        <Text style={styles.textStyle}>{`inside ${myProps.name}`}</Text>
      </View>
    </BottomSheet>
  );
});

const TabComponent = (props: any) => {
  const customBottomSheetRef = useRef<any>(null);

  useEffect(() => {
    customBottomSheetRef.current?.open();
  }, []);

  return (
    <View style={styles.centeredContent}>
      <Text style={styles.textStyle}>{props.route.name}</Text>
      <CustomBottomSheet ref={customBottomSheetRef} name={props.route.name} />
    </View>
  );
};

function App(): JSX.Element {
  return (
    <GestureHandlerRootView style={styles.safeAreaContainer}>
      <SafeAreaProvider style={styles.safeAreaContainer}>
        <NavigationContainer>
          <BottomTab.Navigator>
            <BottomTab.Screen name="home" component={TabComponent} />
            <BottomTab.Screen name="search" component={TabComponent} />
            <BottomTab.Screen name="explore" component={TabComponent} />
            <BottomTab.Screen name="profile" component={TabComponent} />
          </BottomTab.Navigator>
        </NavigationContainer>
      </SafeAreaProvider>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  safeAreaContainer: {
    flex: 1,
    backgroundColor: 'white',
  },
  centeredContent: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  textStyle: {
    fontSize: 24,
    fontWeight: 'bold',
  },
});

export default App;

输出:

CODE SNIPPET OUTPUT IMAGE

评论

0赞 Walter Monecke 11/17/2023
嘿!感谢您的实现 - 我唯一剩下的问题是为什么您认为管理自定义选项卡栏中的状态会导致性能问题?
0赞 Vicky Ahuja 11/17/2023
@WalterMonecke好问题,实际上,每当您的底部工作表内容或自定义底部选项卡内的任何状态发生变化时,它都会重新呈现自定义底部选项卡内的所有代码。这就是为什么它会导致性能问题。