1
razor1895 2023-10-24 00:28:16 +08:00
|
2
razor1895 2023-10-24 00:30:37 +08:00
这是一个精简版本的实现
import { useEffect } from 'react'; import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; import { trigger } from 'react-native-haptic-feedback'; import { BlurView } from '@react-native-community/blur'; import { BottomTabBarProps } from '@react-navigation/bottom-tabs'; import { useQueryClient } from '@tanstack/react-query'; import { TAB_BAR_HEIGHT } from '@/styles'; import { p2d } from '@/utils'; import { pubsub } from '@/utils/pubsub'; import { Badge } from './Badge'; const TabBarIconMap = [ { inactive: require('@/assets/icons/icon-crushes.png'), active: require('@/assets/icons/icon-crushes-focused.png'), style: { width: p2d(24), height: p2d(17), }, }, { inactive: require('@/assets/icons/icon-news.png'), active: require('@/assets/icons/icon-news-focused.png'), style: { width: p2d(23), height: p2d(18.596), }, }, { inactive: require('@/assets/icons/icon-confessions.png'), active: require('@/assets/icons/icon-confessions-focused.png'), style: { width: p2d(18.35), height: p2d(17), }, }, { inactive: require('@/assets/icons/icon-profile.png'), active: require('@/assets/icons/icon-profile-focused.png'), style: { width: p2d(11), height: p2d(17), }, }, ]; const TabBarIcon = ({ focused, index, tabBarBadge, }: { focused: boolean; index: number; tabBarBadge?: string | number; }) => { const map = TabBarIconMap[index]; return ( <View> <FastImage source={focused ? map.active : map.inactive} style={map.style} resizeMode='contain' /> <Badge visible={!!tabBarBadge} style={styles.badge}> {tabBarBadge} </Badge> </View> ); }; let showedInviteModal = false; export function TabBar({ state, descriptors, navigation }: BottomTabBarProps) { // @ts-ignore const bottom = global.bottomInset || 0; const queryClient = useQueryClient(); useEffect(() => { const disposer = pubsub.subscribe('have_shown_swipe_modal', () => { showedInviteModal = true; }); return disposer; }, []); return ( <View style={[styles.container, { bottom: Math.max(bottom, 10) }]}> {Platform.OS === 'ios' && ( <BlurView blurType='xlight' blurAmount={2} style={StyleSheet.absoluteFillObject} /> )} {state.routes.map((route, index) => { const { options } = descriptors[route.key]; const isFocused = state.index === index; const onPress = () => { const event = navigation.emit({ type: 'tabPress', target: route.key, canPreventDefault: true, }); trigger('impactMedium'); if (!isFocused && !event.defaultPrevented) { // The `merge: true` option makes sure that the params inside the tab screen are preserved navigation.navigate({ name: route.name, merge: true }); } }; return ( <TouchableOpacity key={String(index)} accessibilityRole='button' accessibilityState={isFocused ? { selected: true } : {}} accessibilityLabel={options.tabBarAccessibilityLabel} testID={options.tabBarTestID} onPress={onPress} style={styles.item} > <TabBarIcon focused={isFocused} index={index} tabBarBadge={options.tabBarBadge} /> </TouchableOpacity> ); })} </View> ); } const styles = StyleSheet.create({ container: { position: 'absolute', // bottom: 0, // left: 0, height: TAB_BAR_HEIGHT, flexDirection: 'row', // backgroundColor: 'transparent', backgroundColor: 'rgba(255,255,255,0.3)', width: p2d(234), alignSelf: 'center', alignItems: 'center', borderRadius: p2d(10), overflow: 'hidden', }, item: { flex: 1, justifyContent: 'center', alignItems: 'center', }, icon: { width: p2d(18), height: p2d(18), }, badge: { position: 'absolute', right: p2d(-5), top: p2d(-4), }, }); 自己实现 ui 即可 |