如何为react-native-toast-message添加自动隐藏倒计时进度条?
为react-native-toast-message添加自动隐藏进度条的实现方案
问题描述
我希望为react-native-toast-message添加一个状态进度条,用于提示Toast消息何时自动隐藏。但在官方文档中未找到相关配置,想了解基于该库的可行实现方案。
当前代码(App.tsx)
import React from 'react'; import * as SplashScreen from 'expo-splash-screen'; import { Button, Pressable, Text, View } from 'react-native'; import Toast from 'react-native-toast-message'; import { AntDesign, Ionicons as Icon } from '@expo/vector-icons'; // Keep the splash screen visible while we fetch resources SplashScreen.preventAutoHideAsync(); const toastConfig = { success: ({ text1 }: any) => ( <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: 60, width: '100%', paddingLeft: 20, backgroundColor: '#87b64f' }} > <Text style={{ color: '#ffffff', fontSize: 20 }}> {text1} <Icon name="checkmark" size={24} color="#ffffff" /> </Text> <Pressable style={{ justifyContent: 'center', alignItems: 'center', width: 60, height: '100%', marginLeft: 'auto', borderLeftWidth: 1, borderColor: '#ffffff' }} onPress={() => Toast.hide()} > <AntDesign name="close" size={24} color="#ffffff" /> </Pressable> </View> ), error: ({ text1 }: any) => ( <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', height: 60, width: '100%', paddingLeft: 20, backgroundColor: '#f27474' }} > <Text style={{ color: '#ffffff', fontSize: 20 }}>{text1}</Text> <Pressable style={{ justifyContent: 'center', alignItems: 'center', width: 60, height: '100%', marginLeft: 'auto', borderLeftWidth: 1, borderColor: '#ffffff' }} onPress={() => Toast.hide()} > <AntDesign name="close" size={24} color="#ffffff" /> </Pressable> </View> ) }; export default function App(): JSX.Element { return ( <View style={{ display: 'flex', paddingTop: 200, paddingHorizontal: 40, backgroundColor: '#ffffff', height: '100%' }} > <Button title="Show Toast" onPress={() => Toast.show({ topOffset: 0, type: 'success', text1: 'Success' }) } /> <Toast config={toastConfig} /> </View> ); }
效果对比
预期效果

当前效果

实现方案
由于react-native-toast-message官方未提供进度条配置,我们可以通过自定义Toast组件+动画进度条实现,核心是用Animated API绑定Toast显示时长做进度动画:
改造后的完整代码
import React, { useEffect, useRef } from 'react'; import { Button, Pressable, Text, View, Animated } from 'react-native'; import Toast from 'react-native-toast-message'; import { AntDesign, Ionicons as Icon } from '@expo/vector-icons'; import * as SplashScreen from 'expo-splash-screen'; SplashScreen.preventAutoHideAsync(); // 带进度条的自定义Toast组件 const ProgressToast = ({ text1, type, onHide }: { text1: string, type: 'success' | 'error', onHide: () => void }) => { const displayDuration = 3000; // 与Toast.show的duration保持一致 const progressAnim = useRef(new Animated.Value(1)).current; useEffect(() => { // 启动进度条动画:从100%宽度缩至0 const timer = Animated.timing(progressAnim, { toValue: 0, duration: displayDuration, useNativeDriver: false, }).start(() => onHide()); // 动画结束后触发隐藏 return () => timer.stop(); // 组件卸载时终止动画 }, [progressAnim, displayDuration, onHide]); // 插值转换进度条宽度 const progressWidth = progressAnim.interpolate({ inputRange: [0, 1], outputRange: ['0%', '100%'], }); const [bgColor, progressBgColor] = type === 'success' ? ['#87b64f', '#6a993d'] : ['#f27474', '#d9534f']; return ( <View style={{ width: '100%' }}> <View style={{ flexDirection: 'row', alignItems: 'center', height: 60, paddingLeft: 20, backgroundColor: bgColor, }} > <Text style={{ color: '#fff', fontSize: 20, flex: 1 }}> {text1} {type === 'success' && <Icon name="checkmark" size={24} color="#fff" style={{ marginLeft: 8 }} />} </Text> <Pressable style={{ justifyContent: 'center', alignItems: 'center', width: 60, height: '100%', borderLeftWidth: 1, borderColor: '#fff', }} onPress={onHide} > <AntDesign name="close" size={24} color="#fff" /> </Pressable> </View> {/* 底部进度条容器 */} <View style={{ height: 3, backgroundColor: 'rgba(255,255,255,0.3)' }}> <Animated.View style={{ height: '100%', width: progressWidth, backgroundColor: progressBgColor }} /> </View> </View> ); }; const toastConfig = { success: ({ text1, onHide }: any) => ( <ProgressToast text1={text1} type="success" onHide={onHide} /> ), error: ({ text1, onHide }: any) => ( <ProgressToast text1={text1} type="error" onHide={onHide} /> ), }; export default function App(): JSX.Element { return ( <View style={{ flex: 1, paddingTop: 200, paddingHorizontal: 40, backgroundColor: '#fff' }} > <Button title="Show Toast" onPress={() => Toast.show({ topOffset: 0, type: 'success', text1: 'Success', duration: 3000, // 必须和ProgressToast的displayDuration一致 }) } /> <Toast config={toastConfig} /> </View> ); }
关键注意点
- 进度条动画时长必须与
Toast.show中的duration参数完全一致,保证进度走完时Toast刚好隐藏; - 点击关闭按钮时,动画会自动终止并触发隐藏,避免内存泄漏;
- 通过
type参数区分success/error样式,保持原有设计风格; - 进度条使用半透明底色+深色进度条,既不干扰主内容,又能清晰提示剩余时长。
内容的提问来源于stack exchange,提问作者Fiddle Freak
相关产品推荐
相关产品推荐

