From 2aa2b513eb51d084a5e41669b509f8bf3233065b Mon Sep 17 00:00:00 2001 From: oneao Date: Wed, 29 Oct 2025 22:40:19 +0800 Subject: [PATCH] u --- code/app/base-app/package.json | 1 + code/app/base-app/pnpm-lock.yaml | 46 ++++++++++ code/app/base-app/src/app/(tabs)/_layout.tsx | 79 +++++++++++++---- .../app/(tabs)/{index.tsx => app-center.tsx} | 0 code/app/base-app/src/app/(tabs)/chat.tsx | 17 ++++ code/app/base-app/src/app/(tabs)/dating.tsx | 17 ++++ code/app/base-app/src/app/(tabs)/finance.tsx | 17 ++++ .../app/(tabs)/{settings.tsx => profile.tsx} | 0 code/app/base-app/src/app/_layout.tsx | 2 - code/app/base-app/test.html | 84 +++++++++++++++++++ 10 files changed, 245 insertions(+), 18 deletions(-) rename code/app/base-app/src/app/(tabs)/{index.tsx => app-center.tsx} (100%) create mode 100644 code/app/base-app/src/app/(tabs)/chat.tsx create mode 100644 code/app/base-app/src/app/(tabs)/dating.tsx create mode 100644 code/app/base-app/src/app/(tabs)/finance.tsx rename code/app/base-app/src/app/(tabs)/{settings.tsx => profile.tsx} (100%) create mode 100644 code/app/base-app/test.html diff --git a/code/app/base-app/package.json b/code/app/base-app/package.json index 276a09bb..58c82e85 100644 --- a/code/app/base-app/package.json +++ b/code/app/base-app/package.json @@ -25,6 +25,7 @@ "nativewind": "^4.2.1", "react": "19.1.0", "react-native": "0.81.5", + "react-native-curved-bottom-bar": "^3.5.1", "react-native-reanimated": "~3.17.5", "react-native-safe-area-context": "5.4.0", "react-native-screens": "~4.16.0", diff --git a/code/app/base-app/pnpm-lock.yaml b/code/app/base-app/pnpm-lock.yaml index b1600b01..63e4c2df 100644 --- a/code/app/base-app/pnpm-lock.yaml +++ b/code/app/base-app/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: react-native: specifier: 0.81.5 version: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) + react-native-curved-bottom-bar: + specifier: ^3.5.1 + version: 3.5.1(@react-navigation/bottom-tabs@7.5.0(@react-navigation/native@7.1.18(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.4.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) react-native-reanimated: specifier: ~3.17.5 version: 3.17.5(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) @@ -2505,6 +2508,14 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -4356,6 +4367,15 @@ packages: react-native-svg: optional: true + react-native-curved-bottom-bar@3.5.1: + resolution: {integrity: sha512-WG7ZTs+JYXCmGrnXzsYB12DD/UvVdSC4pgem7X5BxXR/bnSgPEHMc0lmGhuRoPS7WgH75w8kncUJFDcwlA75fQ==} + engines: {node: '>= 16.0.0'} + peerDependencies: + '@react-navigation/bottom-tabs': '*' + react: '*' + react-native: '*' + react-native-svg: '*' + react-native-is-edge-to-edge@1.1.7: resolution: {integrity: sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w==} peerDependencies: @@ -4387,6 +4407,12 @@ packages: react: '*' react-native: '*' + react-native-size-scaling@0.5.4: + resolution: {integrity: sha512-GtoE7qcw4ftOigtq6hRTV34nosGw9z6WXNq2l06Uj+yFfvrz6teGjD/E22Jo4raegdTIQmPcMU4/nRRhRLZpAA==} + peerDependencies: + react: '*' + react-native: '*' + react-native-svg@15.12.1: resolution: {integrity: sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==} peerDependencies: @@ -8530,6 +8556,12 @@ snapshots: csstype@3.1.3: {} + d3-path@3.1.0: {} + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + debug@2.6.9: dependencies: ms: 2.0.0 @@ -10822,6 +10854,15 @@ snapshots: transitivePeerDependencies: - supports-color + react-native-curved-bottom-bar@3.5.1(@react-navigation/bottom-tabs@7.5.0(@react-navigation/native@7.1.18(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.4.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): + dependencies: + '@react-navigation/bottom-tabs': 7.5.0(@react-navigation/native@7.1.18(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.4.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) + d3-shape: 3.2.0 + react: 19.1.0 + react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) + react-native-size-scaling: 0.5.4(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) + react-native-svg: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) + react-native-is-edge-to-edge@1.1.7(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 @@ -10865,6 +10906,11 @@ snapshots: react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) warn-once: 0.1.1 + react-native-size-scaling@0.5.4(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): + dependencies: + react: 19.1.0 + react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) + react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): dependencies: css-select: 5.2.2 diff --git a/code/app/base-app/src/app/(tabs)/_layout.tsx b/code/app/base-app/src/app/(tabs)/_layout.tsx index 2a89740c..02833c5a 100644 --- a/code/app/base-app/src/app/(tabs)/_layout.tsx +++ b/code/app/base-app/src/app/(tabs)/_layout.tsx @@ -1,23 +1,70 @@ -import FontAwesome from '@expo/vector-icons/FontAwesome' import { Tabs } from 'expo-router' +import { CircleDollarSign, CircleUserRound, Heart, Layers, MessageSquare } from 'lucide-react-native' +import React, { useRef } from 'react' +import { Animated, Pressable, View } from 'react-native' + +const tabItems = [ + { name: 'finance', icon: }, + { name: 'dating', icon: }, + { name: 'app-center', icon: }, + { name: 'chat', icon: }, + { name: 'profile', icon: }, +] + +// 自定义 TabBar +function CustomTabBar({ state, descriptors, navigation }: any) { + const scales = useRef(tabItems.map(() => new Animated.Value(1))).current + + return ( + + {state.routes.map((route: any, index: number) => { + const item = tabItems.find(i => i.name === route.name) + if (!item) + return null + + const isFocused = state.index === index + const color = isFocused ? '#333333' : '#9ca3af' + + const onPressIn = () => + Animated.spring(scales[index], { toValue: 0.8, useNativeDriver: true }).start() + const onPressOut = () => + Animated.spring(scales[index], { toValue: 1, useNativeDriver: true }).start() + + const onPress = () => { + const event = navigation.emit({ + type: 'tabPress', + target: route.key, + canPreventDefault: true, + }) + if (!isFocused && !event.defaultPrevented) { + navigation.navigate(route.name) + } + } + + return ( + + + {React.cloneElement(item.icon, { color })} + + + ) + })} + + ) +} export default function TabLayout() { return ( - - , - }} - /> - , - }} - /> + }> + {tabItems.map(item => ( + null }} /> + ))} ) } diff --git a/code/app/base-app/src/app/(tabs)/index.tsx b/code/app/base-app/src/app/(tabs)/app-center.tsx similarity index 100% rename from code/app/base-app/src/app/(tabs)/index.tsx rename to code/app/base-app/src/app/(tabs)/app-center.tsx diff --git a/code/app/base-app/src/app/(tabs)/chat.tsx b/code/app/base-app/src/app/(tabs)/chat.tsx new file mode 100644 index 00000000..01e195f0 --- /dev/null +++ b/code/app/base-app/src/app/(tabs)/chat.tsx @@ -0,0 +1,17 @@ +import { StyleSheet, Text, View } from 'react-native' + +export default function Tab() { + return ( + + Chat [Settings] + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, +}) diff --git a/code/app/base-app/src/app/(tabs)/dating.tsx b/code/app/base-app/src/app/(tabs)/dating.tsx new file mode 100644 index 00000000..27bf78b1 --- /dev/null +++ b/code/app/base-app/src/app/(tabs)/dating.tsx @@ -0,0 +1,17 @@ +import { StyleSheet, Text, View } from 'react-native' + +export default function Tab() { + return ( + + heart [Settings] + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, +}) diff --git a/code/app/base-app/src/app/(tabs)/finance.tsx b/code/app/base-app/src/app/(tabs)/finance.tsx new file mode 100644 index 00000000..c6ab032f --- /dev/null +++ b/code/app/base-app/src/app/(tabs)/finance.tsx @@ -0,0 +1,17 @@ +import { StyleSheet, Text, View } from 'react-native' + +export default function Tab() { + return ( + + Tab [Credit] + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, +}) diff --git a/code/app/base-app/src/app/(tabs)/settings.tsx b/code/app/base-app/src/app/(tabs)/profile.tsx similarity index 100% rename from code/app/base-app/src/app/(tabs)/settings.tsx rename to code/app/base-app/src/app/(tabs)/profile.tsx diff --git a/code/app/base-app/src/app/_layout.tsx b/code/app/base-app/src/app/_layout.tsx index b1d8e3bb..67127a41 100644 --- a/code/app/base-app/src/app/_layout.tsx +++ b/code/app/base-app/src/app/_layout.tsx @@ -5,9 +5,7 @@ import * as SplashScreen from 'expo-splash-screen' import { StatusBar } from 'expo-status-bar' import { RefreshCw } from 'lucide-react-native' import { useEffect } from 'react' -import { Image, ScrollView, Text, View } from 'react-native' import { EmptyState } from '@/components/empty-status' -import { Button, ButtonIcon, ButtonText } from '@/components/ui/button' import { GluestackUIProvider } from '@/components/ui/gluestack-ui-provider' import '@/styles/global.css' diff --git a/code/app/base-app/test.html b/code/app/base-app/test.html new file mode 100644 index 00000000..be12b94e --- /dev/null +++ b/code/app/base-app/test.html @@ -0,0 +1,84 @@ + + + + + +Curved TabBar + + + + +
+
+
💰
+
❤️
+
🗂
+
💬
+
👤
+
+ + +