简体   繁体   English

如何在 Tab Navigator React Navigation 5 中始终设置 Stack Navigator 的第一个屏幕

[英]How to set always first screen of Stack Navigator inside Tab Navigator React Navigation 5

React Navigation 5反应导航 5

I've build a StackNavigator inside of a TabNavigator, and the navigation between home screen and other screens is working.我在 TabNavigator 内部构建了一个 StackNavigator,主屏幕和其他屏幕之间的导航正常。 But the problem is,When I move from Tab2 to Tab1 I expect Tab1 always show me first screen of StackNavigator.但问题是,当我从 Tab2 移动到 Tab1 时,我希望 Tab1 始终显示 StackNavigator 的第一个屏幕。

tab1
   -> Stack
        -screen1
        -screen2
tab2

I am on screen2 and then move to tab2 after that then I move back to Tab1 I want to always display screen1.我在 screen2 上,然后移至 tab2,然后我移回 Tab1 我想始终显示 screen1。

I am try to use我正在尝试使用

OnTabPress({navigation})=>{
    navigation.navigate("stackName",{
     screen: "screen1"
   }).
}

Its work but its show me screen2 first then navigate to screen1.它的工作,但它首先显示 screen2 然后导航到 screen1。 Is there any other Solution.有没有其他解决方案。 https://snack.expo.io/@usamasomy/groaning-donut https://snack.expo.io/@usamasomy/groaning-donut

Use unmountOnBlur: true in options.在选项中使用 unmountOnBlur: true 。 Eg.例如。

<Tab.Screen
        name="Stack1"
        component={Stack1}
        options={{
          tabBarLabel: "Stack1",
          unmountOnBlur: true,
        }}
      />

So when you are navigating away from this tab and you're on screen2 of Stack1, you will always come on the first screen of this stackNavigator when coming back to this tab.因此,当您离开此选项卡并位于 Stack1 的屏幕 2 时,当您返回此选项卡时,您将始终出现在此 stackNavigator 的第一个屏幕上。

在此处输入图像描述

initialRouteName= "NAME" is the keyword to make sure you have a default and make sure you use navigate() push() pop() accordingly. initialRouteName= "NAME"是确保您拥有默认值并确保相应地使用navigate() push() pop()的关键字。

Firstly, create a custom TabBar so we can write our own functions executed by onPress首先,创建一个自定义的 TabBar,这样我们就可以编写自己的由onPress执行的函数

function MyTabBar({ state, descriptors, navigation }) {
  return (
    <View style={{ flexDirection: 'row' }}>
      {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 = () => {
            navigation.reset({
              index: 0,
              routes: [{ name: 'Screen1' }],
            }) 

        if (!isFocused && !event.defaultPrevented) {
            navigation.navigate(route.name);
          }      
            }}
        const onLongPress = () => {
          navigation.emit({
            type: 'tabLongPress',
            target: route.key,
          });
        };

Then in the TabScreens override the original TabBar in Tab.Navigator by using tabBar=... then call navigation.reset() with index:0 and routes:{{name: 'Screen1'}} every time MyTabBar is pressed.然后在TabScreens中,通过使用tabBar=...覆盖MyTabBar中的原始TabBar ,然后在每次Tab.Navigator时使用index:0routes:{{name: 'Screen1'}}调用navigation.reset()

const TabScreens = ()=>{
  return(
    <Tab.Navigator  tabBar={props => <MyTabBar {...props} />} initialRouteName="Tab1Screens" >
      <Tab.Screen 
        name      = "Tab1Screens"
        component = {Tab1Screens}
      />
      <Tab.Screen
        name      = "Tab2Screens"
        component = {Tab2Screens}
      />
    </Tab.Navigator>
  )
}

        return (
          <TouchableOpacity
            accessibilityRole="button"
            accessibilityStates={isFocused ? ['selected'] : []}
            accessibilityLabel={options.tabBarAccessibilityLabel}
            testID={options.tabBarTestID}
            onPress={onPress}
            onLongPress={onLongPress}
            style={{ flex: 1 }}
          >
            <Text style={{ color: isFocused ? '#673ab7' : '#222' }}>
              {label}
            </Text>
          </TouchableOpacity>
        );
      })}
    </View>
  );
}

This can be greatly improved eg:这可以大大改善,例如:

-some logic before `navigation.reset()`

-Accessing onPress without creating a new component 

-etc..

finally snack available here: https://snack.expo.io/@karammarrie/customtabbar终于可以在这里买到零食了: https://snack.expo.io/@karammarrie/customtabbar

i have a simple solution is to set initialRouteName= "screen1" in我有一个简单的解决方案是设置 initialRouteName = "screen1"

<Stack.Navigator
      screenOptions={{
        headerShown: false,
      }}
      initialRouteName="screen1"
    >
      <Stack.Screen name="screen1" component={Screen1} />
      <Stack.Screen name="screen2" component={Screen2} />
</Stack.Navigator>

   {/** **/}

if the screen still shows the first screen 2, you just need to comment the line <Stack.Screen name="screen2" component={Screen2} /> and reload the screen, then remove the comment line.如果屏幕仍然显示第一个屏幕 2,您只需注释行<Stack.Screen name="screen2" component={Screen2} />并重新加载屏幕,然后删除注释行。

There is no documentation about it, but the following code worked for me:没有关于它的文档,但以下代码对我有用:

 const navigationComp = useNavigation<StackNavigationProp<Screen1Stack>();

 <Tab.Screen
    name="Screen1 Tab"
    component={Screen1StackScreen}
    listeners={{
          tabPress: () => {
            navigationComp.replace('Screen 1 Child 1');
          },
        }}
  />

The code above always navigates to the 'Screen 1 Child 1' when the "Screen1 Tab" is pressed.当按下“Screen1 Tab”时,上面的代码总是导航到“Screen 1 Child 1”。

like this像这样

e电子

xport default function BottonTab() {
      const tabOffsetValue = useRef(new Animated.Value(0)).current;
      return (
        <View style={{flex: 1, backgroundColor: colors.primaryColor}}>
          <Tab.Navigator
            initialRouteName="Home"
            screenOptions={{
              showLabel: false,
              tabBarShowLabel: false,
              headerShown: false,
              tabBarStyle: {
                backgroundColor: colors.white,
                position: 'absolute',
                bottom: hp(0.51),
                marginHorizontal: wp(2),
                height: hp(8),
                borderRadius: wp(2),
                shadowColor: '#000',
                shadowOpacity: 0.06,
                shadowOffset: {
                  width: 10,
                  height: 10,
                },
                paddingHorizontal: 20,
              },
            }}>
            <Tab.Screen
              name={'Home'}
              component={HomeScreen}
              options={{
                title: 'Home',
                showLabel: false,
                tabBarIcon: ({focused}) => (
                  <View>
                    <FontAwesome5
                      name="home"
                      size={wp(6)}
                      color={
                        focused ? colors.primaryColor : colors.secondaryTextColor
                      }
                    />
                  </View>
                ),
              }}
              listeners={({navigation, route}) => ({
                tabPress: e => {
                  Animated.spring(tabOffsetValue, {
                    toValue: getWidth() * 0,
                    useNativeDriver: true,
                  }).start();
                },
              })}
            />
    
            <Tab.Screen
              name={'HelpDiskScreen'}
              component={HelpDiskScreen}
              options={{
                title: 'HelpDisk',
                tabBarIcon: ({focused}) => (
                  <View>
                    <FontAwesome5
                      name="search"
                      size={wp(6)}
                      color={
                        focused ? colors.primaryColor : colors.secondaryTextColor
                      }
                    />
                  </View>
                ),
              }}
              listeners={({navigation, route}) => ({
                tabPress: e => {
                  Animated.spring(tabOffsetValue, {
                    toValue: getWidth() * 1.22,
                    useNativeDriver: true,
                  }).start();
                },
              })}
            />
    
            <Tab.Screen
              name={'ManageBookingScreen'}
              component={ManageBookingScreen}
              options={{
                title: 'Manage',
                tabBarIcon: ({focused}) => (
                  <View>
                    <Feather
                      name="settings"
                      size={wp(6)}
                      color={
                        focused ? colors.primaryColor : colors.secondaryTextColor
                      }
                    />
                  </View>
                ),
              }}
              listeners={({navigation, route}) => ({
                tabPress: e => {
                  Animated.spring(tabOffsetValue, {
                    toValue: getWidth() * 2.52,
                    useNativeDriver: true,
                  }).start();
                },
              })}
            />
    
            <Tab.Screen
              name={'ParkyingTypesScreen'}
              component={ParkyingTypesScreen}
              options={{
                title: 'Parking',
                tabBarIcon: ({focused}) => (
                  <View>
                    <FontAwesome5
                      name="bell"
                      size={wp(6)}
                      color={
                        focused ? colors.primaryColor : colors.secondaryTextColor
                      }
                    />
                  </View>
                ),
              }}
              listeners={({navigation, route}) => ({
                tabPress: e => {
                  Animated.spring(tabOffsetValue, {
                    toValue: getWidth() * 3.82,
                    useNativeDriver: true,
                  }).start();
                },
              })}
            />
          </Tab.Navigator>
    
          <Animated.View
            style={{
              width: getWidth(),
              marginLeft: getWidth() * 0.58,
              height: 2,
              backgroundColor: colors.primaryColor,
              bottom: hp(7),
              borderRadius: 20,
              transform: [{translateX: tabOffsetValue}],
            }}></Animated.View>
        </View>
      );
    }

Another option is to clear the stack of the navigation before navigating, so when you return to that screen, the navigation starts from the top另一种选择是在导航之前清除导航的堆栈,因此当您返回到该屏幕时,导航从顶部开始

      navigation.dispatch(StackActions.popToTop());
      navigation.navigate("NextScreen");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将底部选项卡导航器添加到堆栈导航中的一个屏幕? - How to add bottom tab navigator to one screen inside stack navigation? 如何始终将初始屏幕推送到堆栈导航器 (react-navigation@5) - How to always push initial screen to stack navigator (react-navigation@5) 如何使用React本机导航创建嵌套导航? (示例:选项卡导航器中的堆栈导航器) - How to use react native navigation to create a nested navigation? (Example: Stack navigator inside a Tab navigator) React 导航:带有选项卡导航器的堆栈导航器不起作用 - React navigation: stack navigator with tab navigator is not working 反应导航 | 如何从嵌套在 Stack Navigator 中的子屏幕更改 Tab Navigator 上的按钮? - React Navigation | How do I change the buttons on a Tab Navigator from a child screen nested in a Stack Navigator? React Navigation-如何将包装堆栈导航器的组件嵌套在选项卡导航器中 - React Navigation - How to nest a component wrapping a stack navigator inside a tab navigator 如何在选项卡导航器中嵌套包装堆栈导航器的组件 - How to nest a component wrapping a stack navigator inside a tab navigator react 反应导航:切换导航器内的嵌套堆栈导航器和选项卡导航器产生2个标头 - React-navigation: nesting stack navigator and tab navigator inside switch navigator results in 2 headers React Native-Tab Navigator内Drawer Navigator内的Stack Navigator - React Native - Stack Navigator inside Drawer Navigator inside Tab Navigator React Navigation (V2):如何在抽屉导航器中设置图标和堆栈导航器的标签? - React Navigation (V2): How to set the Icon and the label of a stack Navigator inside a Drawer Navigator?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM