Expo AV实现视频播放完毕自动回到起始位置的问题
Expo AV视频播放完毕自动回到起始位置的解决方案
问题分析
你的代码有几个关键问题导致重启功能失效:
- 错误的状态访问:你试图通过
video.status获取播放状态,但video是React ref,播放状态存在你定义的status状态变量里,应该用status.didJustFinish。 - 错误的函数执行时机:直接在组件顶层调用
restart(),会在每次组件渲染时执行,初始阶段status是空对象,video.current也可能未完成初始化,无法正确触发逻辑。 - 未利用播放状态更新回调:Expo AV的
onPlaybackStatusUpdate是专门用来监听播放状态变化的,应该在这里处理播放完成的逻辑,而不是单独调用函数。
修正后的代码
import React from 'react'; import { View, TouchableOpacity, StyleSheet } from 'react-native'; import { Video, ResizeMode } from 'expo-av'; import AntDesign from '@expo/vector-icons/AntDesign'; export default function App() { const video = React.useRef(null); const [status, setStatus] = React.useState({}); const handlePlaybackUpdate = (newStatus) => { setStatus(newStatus); // 当视频播放完成且未开启循环时,重置到起始位置 if (newStatus.didJustFinish && !newStatus.isLooping) { // 重置到视频开头 video.current?.seekAsync(0); // 如果需要重置后自动暂停,保留这行;如果要自动重播,换成playFromPositionAsync(0) video.current?.pauseAsync(); } }; return ( <View style={styles.container}> <Video ref={video} style={styles.video} source={require("./assets/big_buck_bunny.mp4")} useNativeControls={false} volume={1.0} resizeMode={ResizeMode.CONTAIN} isLooping={false} onPlaybackStatusUpdate={handlePlaybackUpdate} /> <View style={styles.buttons}> <TouchableOpacity onPress={() => { if (status.isPlaying) { video.current?.pauseAsync(); } else { video.current?.playAsync(); } }} > {status.isPlaying ? ( <AntDesign style={styles.icons} name="pause" size={50} color="white" /> ) : ( <AntDesign style={styles.icons} name="play" size={50} color="white" /> )} </TouchableOpacity> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#000', }, video: { width: '100%', height: '80%', }, buttons: { marginTop: 20, }, icons: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.5, shadowRadius: 3, }, });
关键修改说明
- 合并状态逻辑:把播放状态更新和完成后的重置逻辑放到
handlePlaybackUpdate里,确保每次状态变化都能检查是否播放完成。 - 选择合适的重置方法:
seekAsync(0)只会把视频拉到起始位置,不会自动播放;如果需要播放完成后自动重播,换成playFromPositionAsync(0)即可。 - 增加健壮性:用
?.可选链操作符避免video.current未初始化时调用方法报错。 - 移除无效调用:删掉组件顶层的
restart()调用,所有逻辑都在状态回调中处理。
内容的提问来源于stack exchange,提问作者Alfie
相关产品推荐
相关产品推荐

