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.
127 lines
2.8 KiB
127 lines
2.8 KiB
|
1 month ago
|
/**
|
||
|
|
* 首页底部 Tabs 导航组件
|
||
|
|
*/
|
||
|
|
|
||
|
|
import React, { useState, useCallback } from 'react';
|
||
|
|
import {
|
||
|
|
View,
|
||
|
|
Text,
|
||
|
|
StyleSheet,
|
||
|
|
TouchableOpacity,
|
||
|
|
Dimensions,
|
||
|
|
} from 'react-native';
|
||
|
|
import { useColorScheme } from '@/hooks';
|
||
|
|
import { createThemeStyles } from '@/theme';
|
||
|
|
import Colors from '@/constants/Colors';
|
||
|
|
|
||
|
|
const { width } = Dimensions.get('window');
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 创建主题样式
|
||
|
|
*/
|
||
|
|
const styles = createThemeStyles((colors) => ({
|
||
|
|
container: {
|
||
|
|
backgroundColor: colors.card,
|
||
|
|
borderTopWidth: 1,
|
||
|
|
borderTopColor: colors.border,
|
||
|
|
flexDirection: 'row',
|
||
|
|
justifyContent: 'space-around',
|
||
|
|
alignItems: 'center',
|
||
|
|
paddingBottom: 8,
|
||
|
|
paddingTop: 8,
|
||
|
|
},
|
||
|
|
tabItem: {
|
||
|
|
flex: 1,
|
||
|
|
alignItems: 'center',
|
||
|
|
justifyContent: 'center',
|
||
|
|
paddingVertical: 8,
|
||
|
|
},
|
||
|
|
tabIcon: {
|
||
|
|
fontSize: 24,
|
||
|
|
marginBottom: 4,
|
||
|
|
},
|
||
|
|
tabLabel: {
|
||
|
|
fontSize: 12,
|
||
|
|
color: colors.text + '80',
|
||
|
|
fontWeight: '500',
|
||
|
|
},
|
||
|
|
tabLabelActive: {
|
||
|
|
color: colors.primary,
|
||
|
|
fontWeight: '600',
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
|
||
|
|
interface TabItem {
|
||
|
|
id: string;
|
||
|
|
label: string;
|
||
|
|
icon: string;
|
||
|
|
action: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface BottomTabsProps {
|
||
|
|
theme?: 'light' | 'dark';
|
||
|
|
activeTab?: string;
|
||
|
|
onTabPress?: (tabId: string, action: string) => void;
|
||
|
|
items?: TabItem[];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 默认 Tab 项
|
||
|
|
*/
|
||
|
|
const DEFAULT_TABS: TabItem[] = [
|
||
|
|
{ id: 'recharge', label: '充值', icon: '💰', action: 'recharge' },
|
||
|
|
{ id: 'withdraw', label: '提现', icon: '💳', action: 'withdraw' },
|
||
|
|
{ id: 'activity', label: '活动', icon: '🎉', action: 'activity' },
|
||
|
|
{ id: 'service', label: '客服', icon: '🎧', action: 'service' },
|
||
|
|
{ id: 'help', label: '帮助', icon: '❓', action: 'help' },
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 底部 Tabs 导航组件
|
||
|
|
*/
|
||
|
|
export default function BottomTabs({
|
||
|
|
theme = 'light',
|
||
|
|
activeTab = 'recharge',
|
||
|
|
onTabPress,
|
||
|
|
items = DEFAULT_TABS,
|
||
|
|
}: BottomTabsProps) {
|
||
|
|
const colorScheme = useColorScheme();
|
||
|
|
const actualTheme = theme === 'light' || theme === 'dark' ? theme : colorScheme;
|
||
|
|
const s = styles[actualTheme];
|
||
|
|
const colors = Colors[actualTheme];
|
||
|
|
|
||
|
|
const [selectedTab, setSelectedTab] = useState(activeTab);
|
||
|
|
|
||
|
|
const handleTabPress = useCallback(
|
||
|
|
(tabId: string, action: string) => {
|
||
|
|
setSelectedTab(tabId);
|
||
|
|
onTabPress?.(tabId, action);
|
||
|
|
},
|
||
|
|
[onTabPress]
|
||
|
|
);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<View style={s.container}>
|
||
|
|
{items.map((item) => (
|
||
|
|
<TouchableOpacity
|
||
|
|
key={item.id}
|
||
|
|
style={s.tabItem}
|
||
|
|
onPress={() => handleTabPress(item.id, item.action)}
|
||
|
|
activeOpacity={0.7}
|
||
|
|
>
|
||
|
|
<Text style={s.tabIcon}>{item.icon}</Text>
|
||
|
|
<Text
|
||
|
|
style={[
|
||
|
|
s.tabLabel,
|
||
|
|
selectedTab === item.id && s.tabLabelActive,
|
||
|
|
]}
|
||
|
|
>
|
||
|
|
{item.label}
|
||
|
|
</Text>
|
||
|
|
</TouchableOpacity>
|
||
|
|
))}
|
||
|
|
</View>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|