/**
* 简单的移动端 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',
},
});