import { getDeviceDimensions } from '@/utils/native.utils'; import React, { useEffect, useRef } from 'react'; import { Animated, StyleSheet, Text, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; const { ratio } = getDeviceDimensions(); interface SuccessToastProps { visible: boolean; message: string; duration?: number; backgroundColor?: string; textColor?: string; icon?: string; onHide?: () => void; } export default function SuccessToast({ visible, message, duration = 2000, backgroundColor = '#DF42D0', // 默认使用应用主题色 textColor = '#FFFFFF', icon = '✓', onHide, }: SuccessToastProps) { const animValue = useRef(new Animated.Value(0)).current; const insets = useSafeAreaInsets(); useEffect(() => { if (visible) { // 入场动画 Animated.sequence([ Animated.timing(animValue, { toValue: 1, duration: 300, useNativeDriver: true, }), // 停留时间 Animated.delay(duration - 600), // 减去入场和退场动画时间 // 退场动画 Animated.timing(animValue, { toValue: 0, duration: 300, useNativeDriver: true, }), ]).start(() => { onHide?.(); }); } }, [visible, duration, animValue, onHide]); if (!visible) return null; const translateY = animValue.interpolate({ inputRange: [0, 1], outputRange: [-(insets.top + 60), 0], // 从安全区域上方滑入 }); const opacity = animValue; return ( {icon} {message} ); } const styles = StyleSheet.create({ container: { position: 'absolute', // top 将由组件内部动态计算 left: 15 * ratio, right: 15 * ratio, zIndex: 1000, alignItems: 'center', }, content: { paddingVertical: 12 * ratio, paddingHorizontal: 20 * ratio, borderRadius: 25 * ratio, flexDirection: 'row', alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4, }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 10, }, icon: { fontSize: 16 * ratio, fontWeight: 'bold', marginRight: 8 * ratio, }, text: { fontSize: 14 * ratio, fontWeight: '600', }, });