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.
126 lines
2.8 KiB
126 lines
2.8 KiB
/** |
|
* 首页底部 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> |
|
); |
|
} |
|
|
|
|