You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:45:43