/** * 简单的移动端 Tab Navigator * * 不使用 React Navigation 的 Tab Navigator,而是使用一个简单的自定义实现 * 这样可以完全避免 React Navigation 状态恢复的问题 */ import React, { useEffect, useState, useCallback } from 'react'; import { View, StyleSheet, TouchableOpacity, Text, Dimensions, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { colors, shadows } from '../theme'; import { useTotalUnreadCount } from '../stores'; import { messageManager } from '../stores'; // ==================== 导入屏幕组件 ==================== import { HomeScreen, SearchScreen } from '../screens/home'; import { ScheduleScreen, CourseDetailScreen } from '../screens/schedule'; import { MessageListScreen, NotificationsScreen, PrivateChatInfoScreen, } from '../screens/message'; import { ProfileScreen, SettingsScreen, EditProfileScreen, NotificationSettingsScreen, BlockedUsersScreen, AccountSecurityScreen } from '../screens/profile'; // ==================== 类型定义 ==================== type TabName = 'HomeTab' | 'MessageTab' | 'ScheduleTab' | 'ProfileTab'; // ==================== 常量 ==================== const TAB_BAR_HEIGHT = 64; const TAB_BAR_MARGIN = 14; const TAB_BAR_FLOATING_MARGIN = 12; // ==================== 组件 ==================== /** * 简化的 Stack Navigator 包装 */ function SimpleStackNavigator({ children, screenName }: { children: React.ReactNode; screenName: string; }) { return ( {children} ); } /** * 主组件:SimpleMobileTabNavigator */ export function SimpleMobileTabNavigator() { const insets = useSafeAreaInsets(); const messageUnreadCount = useTotalUnreadCount(); const [activeTab, setActiveTab] = useState('HomeTab'); // 初始化 MessageManager useEffect(() => { messageManager.initialize(); }, []); // 处理 Tab 切换 const handleTabPress = useCallback((tabName: TabName) => { setActiveTab(tabName); }, []); // 渲染当前 Tab 的内容 const renderTabContent = () => { switch (activeTab) { case 'HomeTab': return ; case 'MessageTab': return ; case 'ScheduleTab': return ; case 'ProfileTab': return ; default: return ; } }; // 渲染 Tab Bar 图标 const renderTabIcon = (tabName: TabName, isActive: boolean) => { const iconColor = isActive ? colors.primary.main : colors.text.secondary; const iconSize = isActive ? 26 : 24; switch (tabName) { case 'HomeTab': return ( ); case 'MessageTab': return ( ); case 'ScheduleTab': return ( ); case 'ProfileTab': return ( ); default: return null; } }; // 渲染 Tab Bar 标签 const renderTabLabel = (tabName: TabName, isActive: boolean) => { const labels: Record = { HomeTab: '首页', MessageTab: '消息', ScheduleTab: '课表', ProfileTab: '我的', }; return ( {labels[tabName]} ); }; return ( {/* 内容区域 */} {renderTabContent()} {/* Tab Bar */} {(['HomeTab', 'MessageTab', 'ScheduleTab', 'ProfileTab'] as TabName[]).map( (tabName) => { const isActive = activeTab === tabName; const showBadge = tabName === 'MessageTab' && messageUnreadCount > 0; return ( handleTabPress(tabName)} activeOpacity={0.7} > {renderTabIcon(tabName, isActive)} {showBadge && ( {messageUnreadCount > 99 ? '99+' : messageUnreadCount} )} {renderTabLabel(tabName, isActive)} ); } )} ); } // ==================== 样式 ==================== const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: colors.background.default, }, stackContainer: { flex: 1, }, content: { flex: 1, marginBottom: TAB_BAR_HEIGHT + TAB_BAR_FLOATING_MARGIN * 2, }, tabBar: { position: 'absolute', left: TAB_BAR_MARGIN, right: TAB_BAR_MARGIN, height: TAB_BAR_HEIGHT, backgroundColor: colors.background.paper, borderRadius: 24, borderTopWidth: 1, borderTopColor: `${colors.divider}88`, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', paddingHorizontal: 8, ...shadows.lg, }, tabItem: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: 6, borderRadius: 18, }, tabItemActive: { backgroundColor: `${colors.primary.main}15`, }, tabIconContainer: { position: 'relative', width: 38, height: 30, alignItems: 'center', justifyContent: 'center', borderRadius: 15, }, tabLabel: { fontSize: 12, fontWeight: '600', marginTop: -2, letterSpacing: 0.2, color: colors.text.secondary, }, tabLabelActive: { color: colors.primary.main, }, badge: { position: 'absolute', top: -2, right: -2, backgroundColor: colors.error.main, borderRadius: 10, minWidth: 18, height: 18, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 4, }, badgeText: { color: colors.primary.contrast, fontSize: 10, fontWeight: '600', }, });