This commit is contained in:
oneao committed 2026-04-12 21:21:07 +08:00
1 parent 4fe17847d0
commit 61e29b5f76
3 files changed
+208 -63

No files matched your search

+186 -38
View File
@@ -1,72 +1,220 @@
import { useSafeAreaInsets } from "react-native-safe-area-context";
import React, { ReactNode } from "react";
import { View, Text } from "react-native";
import Ionicons from "@expo/vector-icons/Ionicons";
import AntDesign from "@expo/vector-icons/AntDesign";
import { ChevronLeft, SwatchBook, CircleChevronLeft, CirclePower } from "lucide-react-native";
import { View, Text, Pressable, StyleSheet } from "react-native";
import {
ChevronLeft,
SlidersHorizontal,
CirclePower,
House,
LayoutGrid,
} from "lucide-react-native";
import { Shadow } from "react-native-shadow-2";
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";
import Svg, { Path } from "react-native-svg";
type LayoutProps = {
children: ReactNode;
};
const AnimatedView = Animated.View;
export default function Layout({ children }: LayoutProps) {
const insets = useSafeAreaInsets();
// 返回按钮
const scale = useSharedValue(1);
const style = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
// 右侧按钮动画
const leftScale = useSharedValue(1);
const rightScale = useSharedValue(1);
const leftStyle = useAnimatedStyle(() => ({
transform: [{ scale: leftScale.value }],
opacity: leftScale.value === 1 ? 1 : 0.7,
}));
const rightStyle = useAnimatedStyle(() => ({
transform: [{ scale: rightScale.value }],
opacity: rightScale.value === 1 ? 1 : 0.7,
}));
return (
<View className="flex-1 bg-white">
{/* 内容区域 */}
<View
className="flex-1"
style={{
flex: 1,
paddingTop: insets.top + 44,
paddingBottom: insets.bottom + 56,
}}
>
{children}
</View>
{/* Header */}
<View
pointerEvents="box-none"
className="absolute top-0 left-0 right-0"
style={{
paddingTop: insets.top,
height: insets.top + 48,
}}
style={{ paddingTop: insets.top }}
>
<View className="h-12 flex-row items-center px-3">
{/* 左区域 */}
<View className="h-12 w-12 rounded-full bg-white items-center justify-center shadow-md">
<ChevronLeft size={28} />
<View className="h-12 flex-row items-center mx-3">
{/* 返回按钮 */}
<Pressable
onPressIn={() => {
scale.value = withSpring(0.8);
}}
onPressOut={() => {
scale.value = withSpring(1);
}}
>
<AnimatedView style={style}>
<Shadow
distance={32}
startColor="rgba(0,0,0,0.03)"
endColor="rgba(255,255,255,0)"
offset={[0, 0]}
paintInside={false}
safeRender
style={styles.iconButtonShadow}
>
<ChevronLeft size={24} />
</Shadow>
</AnimatedView>
</Pressable>
{/* 标题 */}
<View className="flex-1 px-4">
<Text className="text-xl font-semibold tracking-tight text-black/90">记账</Text>
</View>
{/* 中间标题 */}
<View className="flex-1 items-center ">
<Text className="text-xl font-semibold text-black">记账</Text>
</View>
{/* 右侧按钮组 */}
<Shadow
distance={32}
startColor="rgba(0,0,0,0.03)"
endColor="rgba(255,255,255,0)"
offset={[0, 0]}
paintInside={false}
safeRender
style={styles.groupShadow}
>
<Pressable
onPressIn={() => {
leftScale.value = withSpring(0.8);
}}
onPressOut={() => {
leftScale.value = withSpring(1);
}}
>
<AnimatedView style={leftStyle} className="w-14 items-center justify-center">
<SlidersHorizontal size={20} />
</AnimatedView>
</Pressable>
{/* 右区域 */}
<View className="w-28 ">
<View className="h-12 flex-row items-center rounded-full bg-white shadow-md overflow-hidden">
<View className="px-4 items-center justify-center">
<SwatchBook size={22} />
</View>
<View className="w-[1px] h-4 bg-black/10" />
<View className="w-[1px] h-4 bg-black/10" />
<View className="px-4 items-center justify-center">
<CirclePower size={22} />
</View>
</View>
</View>
{/* 右按钮 */}
<Pressable
onPressIn={() => {
rightScale.value = withSpring(0.8);
}}
onPressOut={() => {
rightScale.value = withSpring(1);
}}
>
<AnimatedView style={rightStyle} className="w-14 items-center justify-center">
<CirclePower size={20} />
</AnimatedView>
</Pressable>
</Shadow>
</View>
</View>
{/* tabbar */}
<View
style={{
position: "absolute",
left: 0,
right: 0,
bottom: 0,
paddingBottom: insets.bottom,
}}
className="absolute left-0 right-0 bottom-0"
style={{ paddingBottom: insets.bottom + 6 }}
>
<Text>footer</Text>
<View className="m-3">
<Shadow
distance={32}
startColor="rgba(0,0,0,0.03)"
endColor="rgba(255,255,255,0)"
offset={[0, 0]}
paintInside={false}
safeRender
style={styles.tabbarShadown}
>
<View className="w-full h-16 flex-row items-center justify-between">
<View className="flex-1 items-center justify-center">
<House size={24} color="#666" />
<Text className="text-[10px] text-[#666] mt-1">首页</Text>
</View>
<View className="flex-1 items-center justify-center">
<House size={24} color="#666" />
<Text className="text-[10px] text-[#666] mt-1">分类</Text>
</View>
<View className="flex-1 items-center justify-center" style={{ position: "relative" }}>
<Pressable>
<View
style={{
width: 68,
height: 68,
borderRadius: 999,
backgroundColor: "#5B8CFF",
alignItems: "center",
justifyContent: "center",
borderWidth: 8,
borderColor: "white",
}}
>
<LayoutGrid size={24} color="white" />
</View>
</Pressable>
</View>
<View className="flex-1 items-center justify-center">
<House size={24} color="#666" />
<Text className="text-[10px] text-[#666] mt-1">统计</Text>
</View>
<View className="flex-1 items-center justify-center">
<House size={24} color="#666" />
<Text className="text-[10px] text-[#666] mt-1">我的</Text>
</View>
</View>
</Shadow>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
iconButtonShadow: {
borderRadius: 999,
width: 36,
height: 36,
alignItems: "center",
justifyContent: "center",
borderWidth: 0.5,
borderColor: "rgba(255,255,255,0.6)",
},
groupShadow: {
borderRadius: 999,
height: 36,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
borderWidth: 0.5,
borderColor: "rgba(255,255,255,0.6)",
},
tabbarShadown: {
borderRadius: 999,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
borderWidth: 0.5,
borderColor: "rgba(255,255,255,0.6)",
},
});