React Native进度条动画求助:播放暂停控制及弹窗触发
React Native Progress 进度控制逻辑修复方案
先排查几个常见问题:进度状态没正确更新、定时器实例未持久化、进度更新逻辑缺失。下面是完整的可运行代码示例,直接替换你的现有逻辑即可:
import React, { useState, useRef, useCallback, useEffect } from 'react'; import { View, TouchableOpacity, Text, Modal, StyleSheet } from 'react-native'; import { Bar } from 'react-native-progress'; const TaskDetailScreen = () => { // 进度值,范围0-100 const [progress, setProgress] = useState(0); // 是否处于播放状态 const [isPlaying, setIsPlaying] = useState(false); // 是否显示完成弹窗 const [showCompleteModal, setShowCompleteModal] = useState(false); // 保存定时器实例,避免组件重渲染丢失引用 const progressTimer = useRef(null); // 进度更新逻辑 const updateProgress = useCallback(() => { setProgress(prev => { const newProgress = prev + 1; // 进度到100%时触发弹窗并停止定时器 if (newProgress >= 100) { clearInterval(progressTimer.current); setIsPlaying(false); setShowCompleteModal(true); return 100; } return newProgress; }); }, []); // 播放按钮点击事件 const handlePlay = () => { if (!isPlaying) { setIsPlaying(true); // 每隔500ms更新一次进度,可根据需求调整速度 progressTimer.current = setInterval(updateProgress, 500); } }; // 暂停按钮点击事件 const handlePause = () => { if (isPlaying) { clearInterval(progressTimer.current); setIsPlaying(false); } }; // 关闭弹窗 const closeModal = () => { setShowCompleteModal(false); // 可选:重置进度 setProgress(0); }; // 组件卸载时清除定时器,防止内存泄漏 useEffect(() => { return () => { if (progressTimer.current) { clearInterval(progressTimer.current); } }; }, []); return ( <View style={styles.container}> {/* 进度条 */} <Bar progress={progress / 100} // react-native-progress的progress属性接受0-1的数值 width={null} height={20} color="#4CAF50" unfilledColor="#e0e0e0" borderWidth={0} style={styles.progressBar} /> {/* 控制按钮 */} <View style={styles.buttonContainer}> <TouchableOpacity style={styles.button} onPress={handlePlay}> <Text style={styles.buttonText}>Play</Text> </TouchableOpacity> <TouchableOpacity style={styles.button} onPress={handlePause}> <Text style={styles.buttonText}>Pause</Text> </TouchableOpacity> </View> {/* 任务完成弹窗 */} <Modal visible={showCompleteModal} transparent={true} animationType="fade" onRequestClose={closeModal} > <View style={styles.modalOverlay}> <View style={styles.modalContent}> <Text style={styles.modalTitle}>任务完成!</Text> <TouchableOpacity style={styles.modalButton} onPress={closeModal}> <Text style={styles.modalButtonText}>确定</Text> </TouchableOpacity> </View> </View> </Modal> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', backgroundColor: '#fff', }, progressBar: { marginBottom: 30, }, buttonContainer: { flexDirection: 'row', gap: 15, }, button: { flex: 1, backgroundColor: '#2196F3', padding: 12, borderRadius: 8, alignItems: 'center', }, buttonText: { color: '#fff', fontSize: 16, fontWeight: '500', }, modalOverlay: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.5)', }, modalContent: { width: 280, backgroundColor: '#fff', borderRadius: 12, padding: 25, alignItems: 'center', }, modalTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 20, }, modalButton: { backgroundColor: '#4CAF50', paddingHorizontal: 25, paddingVertical: 10, borderRadius: 8, }, modalButtonText: { color: '#fff', fontSize: 16, }, }); export default TaskDetailScreen;
关键注意点:
- 进度值转换:
react-native-progress的progress属性只接受0-1的小数,所以要把你的0-100进度值除以100。 - 定时器持久化:用
useRef保存定时器实例,不然组件重渲染后定时器引用会丢失,导致无法暂停。 - 边界处理:进度到100%时必须清除定时器,同时切换播放状态,避免继续触发更新。
- 内存泄漏防护:组件卸载时通过
useEffect清除定时器,防止后台仍在执行更新逻辑。
如果之前的代码没生效,大概率是没处理上面这几个点,替换成上面的代码后应该就能正常工作了。
内容的提问来源于stack exchange,提问作者Ann37
相关产品推荐
相关产品推荐

