healthapp
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

11 KiB

02-导航和布局设计

目标

配置 React Navigation 导航系统,实现 Tab 导航和 Stack 导航。


UI 设计参考

参考设计稿:files/ui/首页.png

底部 Tab 导航规范

Tab 图标 文字
首页 房屋图标 home 首页
AI问答 对话气泡 chat-processing AI问答
体质分析 心电图 chart-line-variant 体质分析
我的 用户图标 account 我的

Tab 样式规范

const tabBarOptions = {
  activeTintColor: '#10B981',    // 选中颜色
  inactiveTintColor: '#9CA3AF',  // 未选中颜色
  style: {
    height: 60,
    paddingBottom: 8,
    paddingTop: 8,
    backgroundColor: '#FFFFFF',
    borderTopWidth: 1,
    borderTopColor: '#E5E7EB',
  },
  labelStyle: {
    fontSize: 12,
  },
}

导航栏样式

const headerOptions = {
  headerStyle: {
    backgroundColor: '#10B981',
  },
  headerTintColor: '#FFFFFF',
  headerTitleStyle: {
    fontWeight: '600',
  },
}

前置要求

  • 项目结构已初始化
  • React Navigation 已安装

实施步骤

步骤 1:创建导航类型定义

创建 src/navigation/types.ts

import type { NativeStackNavigationProp } from '@react-navigation/native-stack'
import type { BottomTabNavigationProp } from '@react-navigation/bottom-tabs'
import type { CompositeNavigationProp, RouteProp } from '@react-navigation/native'

// Root Stack
export type RootStackParamList = {
  Auth: undefined
  Main: undefined
  Survey: undefined
}

// Auth Stack
export type AuthStackParamList = {
  Login: undefined
  Register: undefined
}

// Main Tab
export type MainTabParamList = {
  ChatTab: undefined
  ConstitutionTab: undefined
  ProfileTab: undefined
}

// Chat Stack
export type ChatStackParamList = {
  ChatList: undefined
  ChatDetail: { id: number }
}

// Constitution Stack
export type ConstitutionStackParamList = {
  ConstitutionHome: undefined
  ConstitutionQuestions: undefined
  ConstitutionResult: undefined
}

// Profile Stack
export type ProfileStackParamList = {
  ProfileHome: undefined
  HealthRecord: undefined
}

// Navigation Props
export type RootNavigationProp = NativeStackNavigationProp<RootStackParamList>

export type AuthNavigationProp = CompositeNavigationProp<
  NativeStackNavigationProp<AuthStackParamList>,
  NativeStackNavigationProp<RootStackParamList>
>

export type MainTabNavigationProp = BottomTabNavigationProp<MainTabParamList>

export type ChatNavigationProp = CompositeNavigationProp<
  NativeStackNavigationProp<ChatStackParamList>,
  MainTabNavigationProp
>

// Route Props
export type ChatDetailRouteProp = RouteProp<ChatStackParamList, 'ChatDetail'>

步骤 2:创建认证导航

创建 src/navigation/AuthNavigator.tsx

import React from 'react'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import type { AuthStackParamList } from './types'
import LoginScreen from '../screens/auth/LoginScreen'
import RegisterScreen from '../screens/auth/RegisterScreen'

const Stack = createNativeStackNavigator<AuthStackParamList>()

const AuthNavigator = () => {
  return (
    <Stack.Navigator
      screenOptions={{
        headerShown: false,
      }}
    >
      <Stack.Screen name="Login" component={LoginScreen} />
      <Stack.Screen name="Register" component={RegisterScreen} />
    </Stack.Navigator>
  )
}

export default AuthNavigator

步骤 3:创建主 Tab 导航

创建 src/navigation/MainTabNavigator.tsx

import React from 'react'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
import type { MainTabParamList } from './types'
import ChatNavigator from './ChatNavigator'
import ConstitutionNavigator from './ConstitutionNavigator'
import ProfileNavigator from './ProfileNavigator'

const Tab = createBottomTabNavigator<MainTabParamList>()

const MainTabNavigator = () => {
  return (
    <Tab.Navigator
      screenOptions={{
        headerShown: false,
        tabBarActiveTintColor: '#667eea',
        tabBarInactiveTintColor: '#999',
        tabBarStyle: {
          height: 60,
          paddingBottom: 8,
          paddingTop: 8,
        },
        tabBarLabelStyle: {
          fontSize: 12,
        },
      }}
    >
      <Tab.Screen
        name="ChatTab"
        component={ChatNavigator}
        options={{
          tabBarLabel: 'AI问诊',
          tabBarIcon: ({ color, size }) => (
            <Icon name="chat-processing" size={size} color={color} />
          ),
        }}
      />
      <Tab.Screen
        name="ConstitutionTab"
        component={ConstitutionNavigator}
        options={{
          tabBarLabel: '体质测评',
          tabBarIcon: ({ color, size }) => (
            <Icon name="account-heart" size={size} color={color} />
          ),
        }}
      />
      <Tab.Screen
        name="ProfileTab"
        component={ProfileNavigator}
        options={{
          tabBarLabel: '我的',
          tabBarIcon: ({ color, size }) => (
            <Icon name="account-circle" size={size} color={color} />
          ),
        }}
      />
    </Tab.Navigator>
  )
}

export default MainTabNavigator

步骤 4:创建子导航器

创建 src/navigation/ChatNavigator.tsx

import React from 'react'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import type { ChatStackParamList } from './types'
import ChatListScreen from '../screens/chat/ChatListScreen'
import ChatDetailScreen from '../screens/chat/ChatDetailScreen'

const Stack = createNativeStackNavigator<ChatStackParamList>()

const ChatNavigator = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="ChatList"
        component={ChatListScreen}
        options={{ title: 'AI问诊' }}
      />
      <Stack.Screen
        name="ChatDetail"
        component={ChatDetailScreen}
        options={{ title: '对话' }}
      />
    </Stack.Navigator>
  )
}

export default ChatNavigator

创建 src/navigation/ConstitutionNavigator.tsx

import React from 'react'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import type { ConstitutionStackParamList } from './types'
import ConstitutionHomeScreen from '../screens/constitution/ConstitutionHomeScreen'
import ConstitutionQuestionsScreen from '../screens/constitution/ConstitutionQuestionsScreen'
import ConstitutionResultScreen from '../screens/constitution/ConstitutionResultScreen'

const Stack = createNativeStackNavigator<ConstitutionStackParamList>()

const ConstitutionNavigator = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="ConstitutionHome"
        component={ConstitutionHomeScreen}
        options={{ title: '体质测评' }}
      />
      <Stack.Screen
        name="ConstitutionQuestions"
        component={ConstitutionQuestionsScreen}
        options={{ title: '体质问卷' }}
      />
      <Stack.Screen
        name="ConstitutionResult"
        component={ConstitutionResultScreen}
        options={{ title: '测评结果' }}
      />
    </Stack.Navigator>
  )
}

export default ConstitutionNavigator

创建 src/navigation/ProfileNavigator.tsx

import React from 'react'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import type { ProfileStackParamList } from './types'
import ProfileHomeScreen from '../screens/profile/ProfileHomeScreen'
import HealthRecordScreen from '../screens/profile/HealthRecordScreen'

const Stack = createNativeStackNavigator<ProfileStackParamList>()

const ProfileNavigator = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="ProfileHome"
        component={ProfileHomeScreen}
        options={{ title: '我的' }}
      />
      <Stack.Screen
        name="HealthRecord"
        component={HealthRecordScreen}
        options={{ title: '健康档案' }}
      />
    </Stack.Navigator>
  )
}

export default ProfileNavigator

步骤 5:创建根导航器

创建 src/navigation/RootNavigator.tsx

import React from 'react'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import { useUserStore } from '../stores/userStore'
import type { RootStackParamList } from './types'
import AuthNavigator from './AuthNavigator'
import MainTabNavigator from './MainTabNavigator'
import SurveyScreen from '../screens/survey/SurveyScreen'

const Stack = createNativeStackNavigator<RootStackParamList>()

const RootNavigator = () => {
  const { isLoggedIn, surveyCompleted } = useUserStore()

  return (
    <Stack.Navigator screenOptions={{ headerShown: false }}>
      {!isLoggedIn ? (
        <Stack.Screen name="Auth" component={AuthNavigator} />
      ) : !surveyCompleted ? (
        <Stack.Screen name="Survey" component={SurveyScreen} />
      ) : (
        <Stack.Screen name="Main" component={MainTabNavigator} />
      )}
    </Stack.Navigator>
  )
}

export default RootNavigator

步骤 6:创建占位页面

创建基础的占位页面组件,后续会详细实现。

创建 src/screens/auth/LoginScreen.tsx

import React from 'react'
import { View, Text, StyleSheet } from 'react-native'

const LoginScreen = () => {
  return (
    <View style={styles.container}>
      <Text>登录页面(待实现)</Text>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
})

export default LoginScreen

(其他占位页面类似创建)


需要创建的文件清单

文件路径 说明
src/navigation/types.ts 导航类型定义
src/navigation/AuthNavigator.tsx 认证导航
src/navigation/MainTabNavigator.tsx Tab 导航
src/navigation/ChatNavigator.tsx 对话导航
src/navigation/ConstitutionNavigator.tsx 体质导航
src/navigation/ProfileNavigator.tsx 个人导航
src/navigation/RootNavigator.tsx 根导航
各占位页面 基础页面组件

导航结构

RootNavigator
├── AuthNavigator(未登录)
│   ├── Login
│   └── Register
├── Survey(未完成调查)
└── MainTabNavigator(已登录且完成调查)
    ├── ChatTab
    │   ├── ChatList
    │   └── ChatDetail
    ├── ConstitutionTab
    │   ├── ConstitutionHome
    │   ├── ConstitutionQuestions
    │   └── ConstitutionResult
    └── ProfileTab
        ├── ProfileHome
        └── HealthRecord

验收标准

  • 导航结构配置正确
  • Tab 导航显示正常
  • Stack 导航跳转正常
  • 登录状态切换导航正常
  • 类型定义完整

预计耗时

30-40 分钟


下一步

完成后进入 04-APP开发/03-用户认证页面.md