diff --git a/code/app/app-rn4/src/app/money/_layout.tsx b/code/app/app-rn4/src/app/money/_layout.tsx index 4a4cacb6..8137bd63 100644 --- a/code/app/app-rn4/src/app/money/_layout.tsx +++ b/code/app/app-rn4/src/app/money/_layout.tsx @@ -1,10 +1,5 @@ import React from "react"; -import { - CircleDollarSignIcon, - ChartNoAxesColumnIcon, - LayoutGridIcon, - PlusIcon, -} from "lucide-react-native"; +import { CircleDollarSignIcon, ChartNoAxesColumnIcon, PlusIcon } from "lucide-react-native"; import ModuleLayout from "@/layouts/ModuleLayout"; const tabs = [ @@ -15,7 +10,7 @@ const tabs = [ }, { - id: "", + id: "/money/add", icon: PlusIcon, isCenter: true, }, diff --git a/code/app/app-rn4/src/app/money/add/index.tsx b/code/app/app-rn4/src/app/money/add/index.tsx new file mode 100644 index 00000000..27d16f92 --- /dev/null +++ b/code/app/app-rn4/src/app/money/add/index.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import { View, Text } from "react-native"; + +export default function Add() { + return ( + + ADD + + ); +} diff --git a/code/app/app-rn4/src/app/money/ana/index.tsx b/code/app/app-rn4/src/app/money/ana/index.tsx new file mode 100644 index 00000000..2164df8f --- /dev/null +++ b/code/app/app-rn4/src/app/money/ana/index.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import { View, Text } from "react-native"; + +export default function Ana() { + return ( + + Ana + + ); +} \ No newline at end of file diff --git a/code/app/app-rn4/src/app/money/home/index.tsx b/code/app/app-rn4/src/app/money/home/index.tsx index bc645931..77d36bc4 100644 --- a/code/app/app-rn4/src/app/money/home/index.tsx +++ b/code/app/app-rn4/src/app/money/home/index.tsx @@ -1,10 +1,19 @@ import React from "react"; import { View, Text, ScrollView } from "react-native"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; export default function Home() { + const insets = useSafeAreaInsets(); + return ( - + Money Home {Array.from({ length: 30 }).map((_, i) => ( diff --git a/code/app/app-rn4/src/components/layout/navbar.tsx b/code/app/app-rn4/src/components/layout/navbar.tsx index bc950e71..01640358 100644 --- a/code/app/app-rn4/src/components/layout/navbar.tsx +++ b/code/app/app-rn4/src/components/layout/navbar.tsx @@ -3,21 +3,34 @@ import { View, Text, StyleProp, ViewStyle, Pressable, StyleSheet } from "react-n import { cn } from "@/utils/cn"; import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated"; import { Shadow } from "react-native-shadow-2"; -import { ChevronLeft, SlidersHorizontal, CirclePower } from "lucide-react-native"; +import { ChevronLeft, SlidersHorizontal, CirclePower, LucideIcon } from "lucide-react-native"; interface NavbarProps { title?: string; + titleIcon?: LucideIcon; showBack?: boolean; onBack?: () => void; + onClose?: () => void; + className?: string; style?: StyleProp; } const AnimatedView = Animated.View; -export default function Navbar({ title, showBack = true, onBack, className, style }: NavbarProps) { +export default function Navbar({ + title, + titleIcon, + showBack = true, + onBack, + onClose, + className, + style, +}: NavbarProps) { + const TitleIcon = titleIcon; + // 返回按钮 const scale = useSharedValue(1); const backAnimatedStyle = useAnimatedStyle(() => ({ @@ -39,56 +52,77 @@ export default function Navbar({ title, showBack = true, onBack, className, styl })); return ( - // - {showBack && ( - { - scale.value = withSpring(0.8); - }} - onPressOut={() => { - scale.value = withSpring(1); - }} - > - - - - - - - )} + + {showBack && ( + { + scale.value = withSpring(0.8); + }} + onPressOut={() => { + scale.value = withSpring(1); + }} + > + + + + + + + )} - {title && ( - - {title} - - )} + {title && ( + + {TitleIcon && } + + {title} + + + )} + - {/* 右按钮 */} { rightScale.value = withSpring(0.8); }} @@ -124,7 +158,6 @@ export default function Navbar({ title, showBack = true, onBack, className, styl - // ); } @@ -137,6 +170,7 @@ const styles = StyleSheet.create({ justifyContent: "center", borderWidth: 0.5, borderColor: "rgba(255,255,255,0.6)", + backgroundColor: "#fff", }, groupShadow: { borderRadius: 999, @@ -146,5 +180,21 @@ const styles = StyleSheet.create({ justifyContent: "center", borderWidth: 0.5, borderColor: "rgba(255,255,255,0.6)", + backgroundColor: "#fff", + }, + titleShadown: { + borderRadius: 999, + height: 36, + + flexDirection: "row", + alignItems: "center", + + justifyContent: "flex-start", + + borderWidth: 0.5, + borderColor: "rgba(255,255,255,0.6)", + paddingHorizontal: 16, + + backgroundColor: "#fff", }, }); diff --git a/code/app/app-rn4/src/components/layout/tabbar.tsx b/code/app/app-rn4/src/components/layout/tabbar.tsx index 212f8f11..2aac638b 100644 --- a/code/app/app-rn4/src/components/layout/tabbar.tsx +++ b/code/app/app-rn4/src/components/layout/tabbar.tsx @@ -2,7 +2,6 @@ import { View, StyleProp, ViewStyle, Pressable, StyleSheet } from "react-native" import { LucideIcon } from "lucide-react-native"; import { cn } from "@/utils/cn"; import { Shadow } from "react-native-shadow-2"; -import { useState } from "react"; import Animated, { useSharedValue, useAnimatedStyle, withTiming } from "react-native-reanimated"; export interface TabbarItem { @@ -22,14 +21,9 @@ export interface TabbarProps { } export default function Tabbar({ tabs, value, onChange, className, style }: TabbarProps) { - const [innerValue, setInnerValue] = useState(tabs[0]?.id); - - const activeTab = value ?? innerValue; + const activeTab = value; const handlePress = (id: string) => { - if (value === undefined) { - setInnerValue(id); - } onChange?.(id); }; @@ -37,8 +31,8 @@ export default function Tabbar({ tabs, value, onChange, className, style }: Tabb @@ -86,15 +80,15 @@ function TabItem({ onPressOut={() => { scale.value = withTiming(1, { duration: 120 }); }} - className="flex-1 items-center justify-center" + className="flex-1 " > - + {tab.title && ( void }} > - {/* */} - void justifyContent: "center", borderWidth: 8, borderColor: "white", - top: -12, + top: -4, }} + > */} + - - {/* */} + + {/* */} @@ -161,14 +156,14 @@ function CenterButton({ tab, onPress }: { tab: TabbarItem; onPress?: () => void const styles = StyleSheet.create({ centerButtonShadown: { - width: 48, - height: 48, + width: 44, + height: 44, borderRadius: 999, alignItems: "center", justifyContent: "center", borderWidth: 1, borderColor: "rgba(0,0,0,0.03)", - backgroundColor: "#fff", + backgroundColor: "#22C55E", }, tabbarShadow: { borderRadius: 999, diff --git a/code/app/app-rn4/src/layouts/ModuleLayout.tsx b/code/app/app-rn4/src/layouts/ModuleLayout.tsx index 4ecd83c4..7d4756ca 100644 --- a/code/app/app-rn4/src/layouts/ModuleLayout.tsx +++ b/code/app/app-rn4/src/layouts/ModuleLayout.tsx @@ -1,42 +1,62 @@ -import React from "react"; import { View } from "react-native"; import Tabbar, { TabbarItem } from "@/components/layout/tabbar"; import Navbar from "@/components/layout/navbar"; -import { Slot } from "expo-router"; import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { Slot, useRouter, usePathname } from "expo-router"; +import { useMemo } from "react"; -interface ModuleLayoutProps { - tabs: TabbarItem[]; -} - -export default function ModuleLayout({ tabs }: ModuleLayoutProps) { +export default function ModuleLayout({ tabs }: { tabs: TabbarItem[] }) { + const router = useRouter(); const insets = useSafeAreaInsets(); + const pathname = usePathname(); + + const activeTabItem = useMemo(() => { + return tabs.find((t) => t.id === pathname); + }, [pathname]); + + function handleClose() { + router.replace("/(tabs)/home"); + } return ( - - - - - - + + - + + + + + + + + { + router.push(id as any); + }} + /> + );