Expo-Router V2 - 选项卡路由内的堆栈屏幕 - [已编辑]

问题描述 投票:0回答:1

编辑 - 03/02/2024

我找到了解决办法。很快就在这里发帖...

项目

我使用 React-Native 和 Expo SDK 49 构建了我的项目,同时使用 Expo-Router V2 作为我的路线。

问题

我想在我的主屏幕(即选项卡屏幕)内有一个堆栈路由。但由于某种原因,当我导航到主页时,只会呈现新的堆栈屏幕。

OBS:我的所有路由文件夹都有:index.tsx、_layout.tsx 和一个组件文件夹

文件夹结构

src
  |-(app) // Both root Stack screens are working. They have: index.tsx & _layout.tsx
    |-(login) // Stack Screen
      |-...
    |-(signup) // Stack Screen
      |-...
    |-(tabs)
      |-(history)
        |-...
      |-(home)
        |-(exercise_details)
        |-components
        |-_layout.tsx
        |-index.tsx
      |-(profile)
        |-...
    |-_layout.tsx

应用程序/_layout.tsx

import { Slot } from "expo-router";

import { StatusBar } from "expo-status-bar";

import { ExerciseProvider } from "@/contexts/ExerciseContext";

import { NativeBaseProvider, Box, Center } from "native-base";

import { AppLoader } from "@/components/AppLoader";

import { THEME } from "@/theme";
import {
  useFonts,
  Roboto_400Regular,
  Roboto_700Bold,
} from "@expo-google-fonts/roboto";

export default function RootLayout() {
  const [fontsLoaded] = useFonts({ Roboto_400Regular, Roboto_700Bold });

  const AppIsBuilding = () => {
    return (
      <Center flexGrow={1} bg="gray.700">
        <AppLoader size="lg" />
      </Center>
    );
  };

  const AppContent = () => {
    return (
      <Box flex={1} bg="gray.700">
        <ExerciseProvider>
          <Slot />
        </ExerciseProvider>
        <StatusBar
          animated
          translucent
          style="light"
          backgroundColor="transparent"
        />
      </Box>
    );
  };

  return (
    <>
      <NativeBaseProvider theme={THEME}>
        {fontsLoaded ? <AppContent /> : <AppIsBuilding />}
      </NativeBaseProvider>
    </>
  );
}

(选项卡)/_layout.tsx

import { Tabs } from "expo-router";

import {
  House,
  UserCircle,
  ClockCounterClockwise,
} from "phosphor-react-native";

import { THEME } from "@/theme";

export default function TabsLayout() {
  return (
    <Tabs
      initialRouteName="(home)"
      screenOptions={{
        tabBarStyle: {
          height: 75,
          backgroundColor: THEME.colors.gray[600],
          borderColor: THEME.colors.gray[600],
        },
        tabBarActiveTintColor: THEME.colors.green[500],
        tabBarInactiveTintColor: THEME.colors.gray[300],
      }}
    >
      <Tabs.Screen
        name="(home)"
        options={{
          title: "",
          headerShown: false,
          tabBarIcon: ({ size, color }) => (
            <House
              size={size}
              color={color}
              weight={color === THEME.colors.green[500] ? "bold" : "regular"}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="(history)"
        options={{
          title: "",
          headerShown: false,
          tabBarIcon: ({ size, color }) => (
            <ClockCounterClockwise
              size={size}
              color={color}
              weight={color === THEME.colors.green[500] ? "bold" : "regular"}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="(profile)"
        options={{
          title: "",
          headerShown: false,
          tabBarIcon: ({ size, color }) => (
            <UserCircle
              size={size}
              color={color}
              weight={color === THEME.colors.green[500] ? "bold" : "regular"}
            />
          ),
        }}
      />
    </Tabs>
  );
}

(主页)/_layout.tsx

import { router, Slot, Tabs } from "expo-router";

import { TouchableOpacity } from "react-native";
import { MaterialIcons } from "@expo/vector-icons";

import { HStack, VStack, Text, Icon, Heading } from "native-base";

import { AppUserPicture } from "@/components/AppUserPicture";

export default function HomeLayout() {
  function handleGoBack() {
    router.canGoBack() && router.back();
  }

  return (
    <>
      <Tabs.Screen
        options={{
          headerShown: true,
          header: () => (
            <HStack
              bg="gray.600"
              padding={6}
              height={117}
              alignItems="center"
              justifyContent="space-between"
              safeArea
            >
              <AppUserPicture w={50} h={50} />

              <VStack flex={1} ml={4}>
                <Text color="gray.100" fontSize="md">
                  Olá,
                </Text>
                <Heading color="gray.100" fontSize="md">
                  Alan Graton
                </Heading>
              </VStack>

              <TouchableOpacity onPress={handleGoBack}>
                <Icon
                  as={MaterialIcons}
                  name="logout"
                  color="gray.200"
                  size={6}
                />
              </TouchableOpacity>
            </HStack>
          ),
        }}
      />
    </>
  );
}

(主页)/(练习_详细信息)/_layout.tsx

import { Slot, Stack } from "expo-router";

export default function ExerciseDetailsLayout() {
  return (
    <Stack initialRouteName="(home)" screenOptions={{ headerShown: false }} />
  );
}

我已经尝试过这样做:

  1. (应用程序)/_layout.tsx

import { Stack } from 'expo-router';

export default function RootLayout() {
  const [fontsLoaded] = useFonts({ Roboto_400Regular, Roboto_700Bold });

  const AppIsBuilding = () => {
    return (
      <Center flexGrow={1} bg="gray.700">
        <AppLoader size="lg" />
      </Center>
    );
  };

  const AppContent = () => {
    return (
      <Box flex={1} bg="gray.700">
        <ExerciseProvider>
          <Stack screenOptions={{ headerShown: false }}>
            <Stack.Screen name="(tabs)" />
          </Stack>
        </ExerciseProvider>
        <StatusBar
          animated
          translucent
          style="light"
          backgroundColor="transparent"
        />
      </Box>
    );
  };

  return (
    <>
      <NativeBaseProvider theme={THEME}>
        {fontsLoaded ? <AppContent /> : <AppIsBuilding />}
      </NativeBaseProvider>
    </>
  );
}

但它只是返回相同的结果;-;

  1. 还尝试从HomeLayout和ExerciseDetailsLayout中删除

    <Slot />
    并得到一个空屏幕(保留了标题和底部TabBar)

  2. 尝试像这样直接在(tabs)/_layout.tsx中声明ExerciseDetails Stack,但也不起作用:

    <Tabs
      initialRouteName="(home)"
      screenOptions={{
        tabBarStyle: {
          height: 75,
          backgroundColor: THEME.colors.gray[600],
          borderColor: THEME.colors.gray[600],
        },
        tabBarActiveTintColor: THEME.colors.green[500],
        tabBarInactiveTintColor: THEME.colors.gray[300],
      }}
    >
      <Tabs.Screen
        name="(home)"
        options={{
          title: "",
          headerShown: false,
          tabBarIcon: ({ size, color }) => (
            <House
              size={size}
              color={color}
              weight={color === THEME.colors.green[500] ? "bold" : "regular"}
            />
          ),
        }}
      />
      <Stack.Screen
        name="(exercise_details)"
        options={{ headerShown: false }}
      />
      <Tabs.Screen
        name="(history)"
        options={{
          title: "",
          headerShown: false,
          tabBarIcon: ({ size, color }) => (
            <ClockCounterClockwise
              size={size}
              color={color}
              weight={color === THEME.colors.green[500] ? "bold" : "regular"}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="(profile)"
        options={{
          title: "",
          headerShown: false,
          tabBarIcon: ({ size, color }) => (
            <UserCircle
              size={size}
              color={color}
              weight={color === THEME.colors.green[500] ? "bold" : "regular"}
            />
          ),
        }}
      />
    </Tabs>
  1. 我找到了这篇文章并尝试实现这些人的结构,但也不起作用:带有嵌套堆栈屏幕的Expo-Router底部选项卡
react-native expo expo-router
1个回答
0
投票

为什么 (home)/_layout.tsx 中没有

<tabs></tabs>
标签? 这可能会让路由器感到困惑。

A 可能对此来说太新了,但是如果没有回购协议,这将是很长的时间。

© www.soinside.com 2019 - 2024. All rights reserved.