React Native能否实现实时播放进度条?指定库使用遇困求助
React Native 实时播放进度条实现方案(基于react-native-sound-player + @react-native-community/slider)
核心疑问解答
react-native-sound-player 的 getInfo() 确实可以用来实现实时进度条,但它是异步Promise方法,无法主动推送播放状态更新,所以需要通过定时轮询的方式定期调用它来获取当前播放时间,从而更新滑块状态。
具体实现步骤及代码示例
以下是适配RN 0.68.4、兼容安卓/iOS的完整实现:
1. 安装依赖(确保已正确安装)
npm install react-native-sound-player @react-native-community/slider # 或 yarn yarn add react-native-sound-player @react-native-community/slider
注意:RN 0.68.4属于较稳定版本,这两个库的最新兼容版本均可直接使用,无需额外link(自动link已支持)。
2. 组件实现代码
import React, { useState, useEffect, useRef } from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import Slider from '@react-native-community/slider'; import SoundPlayer from 'react-native-sound-player'; const AudioPlayer = () => { // 播放状态与进度相关状态 const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [isPlaying, setIsPlaying] = useState(false); // 定时器引用,用于清除轮询 const timerRef = useRef(null); // 初始化音频(替换为你的音频路径) useEffect(() => { try { SoundPlayer.loadSound('your-audio-file.mp3'); // 首次加载时获取总时长 SoundPlayer.getInfo().then(info => { setDuration(info.duration); }); } catch (error) { console.log('音频加载失败:', error); } // 组件卸载时清理资源 return () => { if (timerRef.current) clearInterval(timerRef.current); SoundPlayer.stop(); }; }, []); // 播放/暂停逻辑 const togglePlay = async () => { try { if (isPlaying) { await SoundPlayer.pause(); clearInterval(timerRef.current); } else { await SoundPlayer.play(); // 启动定时轮询,每500ms获取一次播放进度 timerRef.current = setInterval(async () => { const info = await SoundPlayer.getInfo(); setCurrentTime(info.currentTime); }, 500); } setIsPlaying(!isPlaying); } catch (error) { console.log('播放/暂停失败:', error); } }; // 快退10秒 const rewind = async () => { const newTime = Math.max(0, currentTime - 10); await SoundPlayer.seek(newTime); setCurrentTime(newTime); }; // 快进10秒 const forward = async () => { const newTime = Math.min(duration, currentTime + 10); await SoundPlayer.seek(newTime); setCurrentTime(newTime); }; // 滑块拖动结束时跳转播放位置 const handleSliderComplete = async (value) => { await SoundPlayer.seek(value); setCurrentTime(value); }; // 格式化时间为 mm:ss const formatTime = (seconds) => { const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; }; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}> <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}> <TouchableOpacity onPress={rewind} style={{ padding: 10 }}> <Text>快退10s</Text> </TouchableOpacity> <TouchableOpacity onPress={togglePlay} style={{ padding: 10 }}> <Text>{isPlaying ? '暂停' : '播放'}</Text> </TouchableOpacity> <TouchableOpacity onPress={forward} style={{ padding: 10 }}> <Text>快进10s</Text> </TouchableOpacity> </View> <Slider style={{ width: '100%', height: 40 }} minimumValue={0} maximumValue={duration} value={currentTime} onSlidingComplete={handleSliderComplete} minimumTrackTintColor="#000000" maximumTrackTintColor="#cccccc" /> <View style={{ flexDirection: 'row', justifyContent: 'space-between', width: '100%', marginTop: 10 }}> <Text>{formatTime(currentTime)}</Text> <Text>{formatTime(duration)}</Text> </View> </View> ); }; export default AudioPlayer;
关键注意事项
- 定时器清理:必须在组件卸载或暂停播放时清除定时器,避免内存泄漏。
- 音频路径处理:安卓和iOS的音频文件放置路径不同,需确保路径正确(安卓放在
android/app/src/main/res/raw,iOS放在项目资源中)。 - 异常捕获:所有
react-native-sound-player的异步方法都要加try/catch,避免因音频加载失败、播放中断等导致崩溃。 - 滑块交互:仅在
onSlidingComplete时调用seek(),避免拖动过程中频繁跳转影响性能。
内容的提问来源于stack exchange,提问作者user551352
相关产品推荐
相关产品推荐

