Expo Router: Achieve a back navigation from nested Native Stack under Tab Stack when navigating to parent router - Stack Overflo

I have a following Expo Router folder structure- (tabs)- _layout.tsx - home- messages.tsx- qr.tsx- tr

I have a following Expo Router folder structure

- /(tabs)
    - _layout.tsx 
    - home
    - messages.tsx
    - qr.tsx
    - transactions.tsx
    - /profile
        - _layout.tsx
        - account.tsx
        - security.tsx

In general, the navigation works fine, when navigating forward but can cause unwanted issues when navigating backwards.

If a user is currently for example on "Profile > Account" screen, he can navigate to "Profile" screen by tapping on Back button. But if the user instead of tapping on back button taps on Profile tab in the Tab toolbar again, then there is a strange behavior of the Navigation. It shortly switches to actual "Profile" screen but still shows the "Account" screen. If the Profile tab is tapped again, then the "Profile" screen is displayed, but from this point on the user can "navigate back" to the "Account" screen. The reason behind all this is I guess because the navigation still goes forward when going to the "Profile" screen.

The desired behavior is that if a user taps on Profile tab in tab toolbar when he is currently in a sub-screen like "Account" it should be the same behavior as pressing on back button. I don't know how to prevent the default behavior and manipulate the navigation in such a way. The closest example of such behavior would be the Facebook iOS app. There exactly this is achieved.

/(tabs)/_layout.tsx

export default function TabsLayout() {
  const { bottom } = useSafeAreaInsets()

  return (
    <Tabs
      initialRouteName="home"
      screenOptions={{
        tabBarHideOnKeyboard: true,
        tabBarStyle: [$tabBar, { height: 40 }],
        tabBarActiveTintColor: colors.text,
        tabBarInactiveTintColor: colors.text,
        tabBarLabelStyle: $tabBarLabel,
      }}
    >
      <Tabs.Screen
        name="home"
        options={{
          href: "/home",
          headerShown: false,
          tabBarAccessibilityLabel: translate("tabsNavigator:homeTab"),
          tabBarLabel: translate("tabsNavigator:homeTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="home"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="messages"
        options={{
          href: "/messages",
          headerShown: false,
          tabBarAccessibilityLabel: translate("tabsNavigator:messagesTab"),
          tabBarLabel: translate("tabsNavigator:messagesTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="message-bulleted"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="qr"
        options={{
          href: "/qr",
          headerShown: false,
          tabBarAccessibilityLabel: translate("tabsNavigator:QRTab"),
          tabBarLabel: translate("tabsNavigator:QRTab"),
          tabBarIcon: ({ focused }) => (
            <View style={$tabBarIconQRCode}>
              <MaterialCommunityIcons
                name="qrcode-scan"
                color={focused ? colors.palette.accent600 : colors.palette.neutral600}
                size={tabBarIconSize}
              />
            </View>
          ),
          tabBarIconStyle: {
            transform: `translateY(${-tabBarIconSize / 2}px)`,
          },
        }}
      />
      <Tabs.Screen
        name="transactions"
        options={{
          href: "/transactions",
          headerShown: true,
          headerTitle: "Transactions history",
          headerShadowVisible: true,
          tabBarAccessibilityLabel: translate("tabsNavigator:transactionsTab"),
          tabBarLabel: translate("tabsNavigator:transactionsTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="transfer"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="profile"
        options={{
          href: "/profile",
          headerShown: false,
          headerTitle: "Profile",
          tabBarAccessibilityLabel: translate("tabsNavigator:profileTab"),
          tabBarLabel: translate("tabsNavigator:profileTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="account-circle"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
    </Tabs>
  )
}

/(tabs)/profile/_layout.tsx

export default function ProfileLayout() {
  return (
    <Stack
      screenOptions={{
        headerShown: true,
      }}
    />
  )
}

Any thoughts on how this could be achieved?

I have a following Expo Router folder structure

- /(tabs)
    - _layout.tsx 
    - home
    - messages.tsx
    - qr.tsx
    - transactions.tsx
    - /profile
        - _layout.tsx
        - account.tsx
        - security.tsx

In general, the navigation works fine, when navigating forward but can cause unwanted issues when navigating backwards.

If a user is currently for example on "Profile > Account" screen, he can navigate to "Profile" screen by tapping on Back button. But if the user instead of tapping on back button taps on Profile tab in the Tab toolbar again, then there is a strange behavior of the Navigation. It shortly switches to actual "Profile" screen but still shows the "Account" screen. If the Profile tab is tapped again, then the "Profile" screen is displayed, but from this point on the user can "navigate back" to the "Account" screen. The reason behind all this is I guess because the navigation still goes forward when going to the "Profile" screen.

The desired behavior is that if a user taps on Profile tab in tab toolbar when he is currently in a sub-screen like "Account" it should be the same behavior as pressing on back button. I don't know how to prevent the default behavior and manipulate the navigation in such a way. The closest example of such behavior would be the Facebook iOS app. There exactly this is achieved.

/(tabs)/_layout.tsx

export default function TabsLayout() {
  const { bottom } = useSafeAreaInsets()

  return (
    <Tabs
      initialRouteName="home"
      screenOptions={{
        tabBarHideOnKeyboard: true,
        tabBarStyle: [$tabBar, { height: 40 }],
        tabBarActiveTintColor: colors.text,
        tabBarInactiveTintColor: colors.text,
        tabBarLabelStyle: $tabBarLabel,
      }}
    >
      <Tabs.Screen
        name="home"
        options={{
          href: "/home",
          headerShown: false,
          tabBarAccessibilityLabel: translate("tabsNavigator:homeTab"),
          tabBarLabel: translate("tabsNavigator:homeTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="home"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="messages"
        options={{
          href: "/messages",
          headerShown: false,
          tabBarAccessibilityLabel: translate("tabsNavigator:messagesTab"),
          tabBarLabel: translate("tabsNavigator:messagesTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="message-bulleted"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="qr"
        options={{
          href: "/qr",
          headerShown: false,
          tabBarAccessibilityLabel: translate("tabsNavigator:QRTab"),
          tabBarLabel: translate("tabsNavigator:QRTab"),
          tabBarIcon: ({ focused }) => (
            <View style={$tabBarIconQRCode}>
              <MaterialCommunityIcons
                name="qrcode-scan"
                color={focused ? colors.palette.accent600 : colors.palette.neutral600}
                size={tabBarIconSize}
              />
            </View>
          ),
          tabBarIconStyle: {
            transform: `translateY(${-tabBarIconSize / 2}px)`,
          },
        }}
      />
      <Tabs.Screen
        name="transactions"
        options={{
          href: "/transactions",
          headerShown: true,
          headerTitle: "Transactions history",
          headerShadowVisible: true,
          tabBarAccessibilityLabel: translate("tabsNavigator:transactionsTab"),
          tabBarLabel: translate("tabsNavigator:transactionsTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="transfer"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="profile"
        options={{
          href: "/profile",
          headerShown: false,
          headerTitle: "Profile",
          tabBarAccessibilityLabel: translate("tabsNavigator:profileTab"),
          tabBarLabel: translate("tabsNavigator:profileTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="account-circle"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
    </Tabs>
  )
}

/(tabs)/profile/_layout.tsx

export default function ProfileLayout() {
  return (
    <Stack
      screenOptions={{
        headerShown: true,
      }}
    />
  )
}

Any thoughts on how this could be achieved?

Share Improve this question edited Mar 10 at 15:28 f.bele asked Mar 10 at 13:51 f.belef.bele 3974 silver badges17 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

If anybody is ever interested in such a solution, I've got it to work. The solution is that you have to define the <Tabs.Screen /> in the _layout of the path itself. Apart from that you need to turn of the lazy option because otherwise it doesn't generate the tab properly.

export default function TabsLayout() {
  const { bottom } = useSafeAreaInsets()

  return (
    <Tabs
      initialRouteName="home"
      screenOptions={{
        lazy: false,
        tabBarHideOnKeyboard: true,
        tabBarStyle: [$tabBar, { height: 40 }],
        tabBarActiveTintColor: colors.text,
        tabBarInactiveTintColor: colors.text,
        tabBarLabelStyle: $tabBarLabel,
      }}
    >
      <Tabs.Screen
        name="home"
        options={{
          href: "/home",
          headerShown: false,
          lazy: true,
          tabBarAccessibilityLabel: translate("tabsNavigator:homeTab"),
          tabBarLabel: translate("tabsNavigator:homeTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="home"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="messages"
        options={{
          href: "/messages",
          headerShown: false,
          lazy: true,
          tabBarAccessibilityLabel: translate("tabsNavigator:messagesTab"),
          tabBarLabel: translate("tabsNavigator:messagesTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="message-bulleted"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="qr"
        options={{
          href: "/qr",
          headerShown: false,
          lazy: true,
          tabBarAccessibilityLabel: translate("tabsNavigator:QRTab"),
          tabBarLabel: translate("tabsNavigator:QRTab"),
          tabBarIcon: ({ focused }) => (
            <View style={$tabBarIconQRCode}>
              <MaterialCommunityIcons
                name="qrcode-scan"
                color={focused ? colors.palette.accent600 : colors.palette.neutral600}
                size={tabBarIconSize}
              />
            </View>
          ),
          tabBarIconStyle: {
            transform: `translateY(${-tabBarIconSize / 2}px)`,
          },
        }}
      />
      <Tabs.Screen
        name="transactions"
        options={{
          href: "/transactions",
          headerShown: true,
          headerTitle: "Transactions history",
          headerShadowVisible: true,
          lazy: true,
          tabBarAccessibilityLabel: translate("tabsNavigator:transactionsTab"),
          tabBarLabel: translate("tabsNavigator:transactionsTab"),
          tabBarIcon: ({ focused }) => (
            <MaterialCommunityIcons
              name="transfer"
              color={focused ? colors.palette.accent600 : colors.palette.neutral600}
              size={tabBarIconSize}
            />
          ),
        }}
      />
    </Tabs>
  )
}
export default function ProfileLayout() {
  return (
    <>
        <Tabs.Screen
            name="profile"
            options={{
              href: "/profile",
              headerShown: false,
              headerTitle: "Profile",
              lazy: false,
              tabBarAccessibilityLabel: translate("tabsNavigator:profileTab"),
              tabBarLabel: translate("tabsNavigator:profileTab"),
              tabBarIcon: ({ focused }) => (
                <MaterialCommunityIcons
                  name="account-circle"
                  color={focused ? colors.palette.accent600 : colors.palette.neutral600}
                  size={tabBarIconSize}
                />
              ),
            }}
          />
        <Stack
          screenOptions={{
            headerShown: true,
          }}
        />
    </>
  )
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744843612a4596704.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信