React导航|如何从嵌套在堆栈导航器中的子屏幕更改选项卡导航器上的按钮?

qfe3c7zg  于 2023-01-14  发布在  React
关注(0)|答案(1)|浏览(244)

我有一个标签栏,看起来像这样:

两个侧边按钮是堆栈导航器(学习和日志),中间按钮需要导航日志堆栈,根据用户在日志堆栈中的屏幕,它需要说和做不同的事情。

const Tab = createBottomTabNavigator();

const TabBarIcon = ({ icon, title, focused }) => {
  return (
    <View style={styles.iconContainer}>
      <FontAwesomeIcon
        icon={icon}
        color={focused ? Colors.neutral[4] : Colors.neutral[6]}
        size={24}
        style={styles.icon}
      />
      <Text style={[styles.iconText, focused && styles.iconTextFocused]}>
        {title}
      </Text>
    </View>
  );
};

const NullScreen = () => null;

const TabNavigator = () => {
  return (
    <Tab.Navigator
      initialRouteName="Journal"
      screenOptions={({ route }) => ({
        ...defaultNavOptions,
        headerShown: false,
        tabBarStyle: { backgroundColor: Colors.neutral[3] },
        tabBarShowLabel: false,
      })}
    >
      <Tab.Screen
        name="Learn"
        component={LearnStackNavigator}
        options={{
          tabBarIcon: ({ focused }) => (
            <TabBarIcon
              focused={focused}
              title={'Learn'}
              icon={faUserGraduate}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Null Screen"
        component={NullScreen}
        options={{
          tabBarButton: ({ focused }) => (
            <View
              style={{
                position: 'relative',
                bottom: 25,
                width: 80,
                height: 80,
                borderRadius: '50%',
                backgroundColor: 'grey',

                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                shadowColor: 'black',
                shadowOpacity: 0.3,
                shadowOffset: { width: 0, height: 2 },
                shadowRadius: 3,
              }}
            >
              <TouchableOpacity onPress={() => Alert.alert('hello world')}> // This is the button that I want use for useful things
                <View style={[styles.iconContainer, styles.paddingBottom10]}>
                  <FontAwesomeIcon
                    icon={faPlus}
                    color={focused ? Colors.neutral[4] : Colors.neutral[6]}
                    size={32}
                  />
                  <Text style={styles.iconText}>{'Add Sport'}</Text>
                </View>
              </TouchableOpacity>
            </View>
          ),
        }}
      />

      <Tab.Screen
        name="Journal"
        component={LogbookStackNavigator}
        options={{
          tabBarIcon: ({ focused }) => (
            <TabBarIcon focused={focused} title={'Journal'} icon={faPenAlt} />
          ),
        }}
      />
    </Tab.Navigator>
  );
};

下面是LogbookStackNavigator的外观:

const LogbookStack = createStackNavigator();

const LogbookStackNavigator = () => {
  return (
    <LogbookStack.Navigator
      screenOptions={{
        ...defaultNavOptions,
        headerBackTitleVisible: false,
      }}
    >
      <LogbookStack.Screen
        name="Screen1"
        component={screen1Component}
        options={defaultNavOptions}
      />
      <LogbookStack.Screen
        name="Screen2"
        component={screen2Component}
        options={defaultNavOptions}
      />
      <LogbookStack.Screen
        name="Screen3"
        component={screen3Component}
        options={entryScreenOptions}
      />
      <LogbookStack.Screen
        name="Screen4"
        component={screen4Component}
        options={SaveLogbookScreenOptions}
      />
      <LogbookStack.Screen
        name="Screen5"
        component={screen1Component5}
        options={defaultNavOptions}
      />
    </LogbookStack.Navigator>
  );
};

我知道如何使用navigation. setOptions,但它只影响直接的父导航器,而不影响祖父导航器。
我尝试的另一件事是在页面上做一个大圆圈按钮,但是它总是呈现在标签导航器的下面。如果有一种方法可以让它呈现在上面,我想我可以直接使用它。我尝试了'position:"absolute"等等,它总是呈现在标签导航器下面。事实上,我不得不在标签导航器中做一个虚拟屏幕来给我顶部的按钮。
我需要能够做的是使用标签导航器上的大圆圈按钮,在LogbookStackNavigator中导航到不同的屏幕。我该怎么做?
另外,我需要根据LogbookStackNavigator所在的屏幕将标题从"添加运动"更改为"添加"。
谢谢你的帮忙

sbtkgmzw

sbtkgmzw1#

终于明白了,你必须使用react-native-portalize,只要把你想呈现的元素 Package 在<Portal></Portal>.中,这将把它放在底部标签导航器的上方。

import { Portal } from 'react-native-portalize';

const FooterButton = () => {
return(
    <Portal>
      <View>
       <Text>I appear above the Tab Navigator!</Text>
      </View>
    </Portal>
);
export default FooterButton;

不要忘记将整个应用程序 Package 在Host:

//In app.js
import { Host } from 'react-native-portalize';

const App = () => {
return (
    <Host>
       <NavigationContainer>
          <AppNavigator />
       </NavigationContainer>
    </Host>
)
}
export default App;

注意:当导航器导航到另一个屏幕时,门户中的元素不会被清除。因此,为了解决这个问题,你必须只在屏幕处于活动状态时显示门户。谢天谢地,React Navigation 5+提供了一个useIsFocused钩子,完美地完成了这一点。

import { Portal } from 'react-native-portalize';
import { useIsFocused } from '@react-navigation/native';

const FooterButton = () => {
  const isFocused = useIsFocused();

  // Only display the button when screen is focused. Otherwise, it doesn't go away when you switch screens
  return isFocused ? (
    <Portal>
      <View style={styles.buttonContainer}>
        <View style={styles.footer}>{props.children}</View>
      </View>
    </Portal>
  ) : null;
};
export default FooterButton;

如果需要模态样式的弹出窗口,可以 Package react-native-modalize并使用react-native-modalize Package 它
Thanks to livin52 on Reddit for the solution

相关问题