React Native - 滑动时隐藏组件

React Native - hide components on swipe

我有一个布局,您可以在其中使用 React Navigation 5 的 createMaterialTopTabNavigator 水平滑动或使用底部的按钮在屏幕之间转换。该按钮出现在每个屏幕上,我想在滑动过程中隐藏它,并在滑动停止时重新出现。

有谁知道这是否可行?

const Introduction1 = () => {
    return (
        <View style={styles.container}>
            <Text style={{ ...globalStyles.hTitle, ...globalStyles.h1 }}>Welcome</Text>
            <Text style={globalStyles.text}>
                Before you start there is a short introduction available.
            </Text>
            <Text style={{ ...globalStyles.text, ...globalStyles.bold }}>Do you want to see it?</Text>

            <BottomButtons name="Continue" destination="Introduction2" />
        </View>
    );
function SwiperNav() {
    return (
        <Swipe.Navigator
            tabBarOptions={{
                style: {
                    display: 'none'
                }
            }}>
            <Swipe.Screen name="Introduction1" component={Introduction1} />
            <Swipe.Screen name="Introduction2" component={Introduction2} />
            <Swipe.Screen name="Introduction3" component={Introduction3} />
            <Swipe.Screen name="Introduction4" component={Introduction4} />
            <Swipe.Screen name="Introduction5" component={Introduction5} />
        </Swipe.Navigator>
    );
}

原回答

我推荐一种不同的方法。在滑动时隐藏元素很困难(根据我自己的经验)并且根据反应导航文档不推荐:

Some tab navigators such as bottom tab navigator also have a tabBarVisible option which can be used to hide the tab bar based on instructions in the Screen options resolution guide. However, we don't recommend using it since showing/hiding the tab bar mid-navigation can affect the animation of the stack navigator causing glitchy behaviour.

我的方法是在导航器之外定义继续按钮。

首先在您的目录根目录下创建一个如下所示的 RootNavigation 文件。

import * as React from 'react';

export const navigationRef = React.createRef();

export function getCurrentRouteName() {
  return navigationRef.current?.getCurrentRoute().name;
}

export function navigate(name, params) {
  navigationRef.current?.navigate(name, params);
}

这个 RootNavigation 文件的想法是访问 navigation 属性并从我们的按钮中获取当前路由名称。如果按钮放置在导航器之外,则这是不可能的。

将 navigationRef 传递给您的 NavigationContainer

import * as RootNavigation from './RootNavigation';
// ...
const App = () => {
  return (
    <NavigationContainer ref={RootNavigation.navigationRef}>
      <SwiperNav />
      <BottomButtons name="Continue" />
    </NavigationContainer>
  );
}

下面的函数是用来根据当前的路线名称来决定继续按钮应该去的下一条路线。如果你想要你可以 通过使用 constantsenums 作为路由名称来清理代码。

const getSwipeNavigatorNextDestination = currentRouteName => {
  switch (currentRouteName) {
    case 'Introduction1':
      return 'Introduction2';
      break;
    case 'Introduction2':
      return 'Introduction3';
      break;
    // etc...
  }
};

我不知道你的 BottomButtons 组件到底是什么样子,但是 重要的是你定义了一个函数来处理 onPress 你在哪里 检索下一个目的地并使用 RootNavigation.

导航至该目的地
const BottomButtons = ({name}) => {
  const handleBtnNavigate = () => {
    const nextDestination = getSwipeNavigatorNextDestination(
      RootNavigation.getCurrentRouteName(),
    );
    RootNavigation.navigate(nextDestination)
  };
  return <Button title={name} onPress={() => handleBtnNavigate()} />;
};

如果您想了解更多关于 RootNavigation 的想法,您可以参考文档:https://reactnavigation.org/docs/navigating-without-navigation-prop/

有什么不清楚的可以评论,我会澄清的。

原始答案的扩展

您应该在您的应用程序中只使用一个 NavigationContainer。如果您想在导航到不属于介绍屏幕的屏幕后隐藏继续按钮,我建议更改以下内容:

const App = () => {
  const [isShowingIntroduction, setIsShowingIntroduction] = useState(true);

  return (
    <NavigationContainer ref={RootNavigation.navigationRef}>
      <SwiperNav />
      {isShowingIntroduction && (
        <BottomButtons
          name="Continue"
          setIsShowingIntroduction={setIsShowingIntroduction}
        />
      )}
    </NavigationContainer>
  );
};

有条件地显示继续按钮。

const BottomButtons = ({name, setIsShowingIntroduction}) => {
  const handleBtnNavigate = () => {
    const nextDestination = getSwipeNavigatorNextDestination(
      RootNavigation.getCurrentRouteName(),
    );
    if (nextDestination == 'ScreenNotPartOfIntroduction') {
      setIsShowingIntroduction(false);
    }
    RootNavigation.navigate(nextDestination);
  };
  return <Button title={name} onPress={() => handleBtnNavigate()} />;
};

我在这里所做的是在应用程序组件(继续按钮的父组件)中创建一个状态变量并伴随 setter。这允许我们将 setter 函数传递给继续按钮。然后在按钮组件内部我们可以创建一个检查:如果 nextDestination 是一个屏幕名称而不是介绍屏幕名称集的一部分,则调用 setIsShowingIntroduction(false)。应用程序组件更新并隐藏按钮,然后导航到 nextDestination.