RN 使用react-native-video 播放视频(包含进度条、全屏)
<p><span style="font-size: 18px">21年12月3日,阐述上有问题:应该将问题拆分,不该将代码整一大堆,看着很不舒适</span></p><p> </p>
<p>目标需求:<br>1. 实现视频播放</p>
<p>2. 进度条</p>
<p>3. 进入全屏</p>
<p>目标图是这样的:<br><img src="https://img2018.cnblogs.com/i-beta/1723157/201912/1723157-20191212173653375-1313575514.png"></p>
<p> </p>
<p> </p>
<p> </p>
<p>需要三个组件</p>
<p>1. 播放视频组件, react-native-video 官网地址 https://www.npmjs.com/package/react-native-video#allowsexternalplayback<br></p>
<p>2. 进度条,官网上提供的 slider组件我忘记说的什么原因,即将停止支持,我找了<strong>react-native-silder</strong> 这个个第三方包 官网地址 https://github.com/react-native-community/react-native-slider#onvaluechange<br>现在<strong>react-native-silder</strong> 的一些生命周期方法都是警告,因为react很多声明周期函数,已经废弃或改名字 ,我目前在尝试 https://github.com/callstack/react-native-slider</p>
<p>3. 全屏播放,react-native-orientation这个包有问题,因为RN 将对 rnpm 换一种支持策略 ,所以选择用 <strong>react-native-orientation-locker</strong> 官网地址 https://github.com/wonday/react-native-orientation-locker</p>
<p> </p>
<p>后面的就直接上代码了</p>
<div class="cnblogs_code">
<pre>import React from 'react'<span style="color: rgba(0, 0, 0, 1)">;
import {View,Text,StyleSheet,TouchableWithoutFeedback,TouchableOpacity,Dimensions} from </span>'react-native'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">导入Video组件</span>
import Video from 'react-native-video'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 导入 Silder组件</span>
import Slider from '@react-native-community/slider'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 屏幕方向锁定: 他需要改变 原来Android文件代码,当然适配两端的话,IOS也是需要更改的。</span>
import Orientation from 'react-native-orientation-locker'<span style="color: rgba(0, 0, 0, 1)">;
let screenWidth</span>= Dimensions.get('window'<span style="color: rgba(0, 0, 0, 1)">).width;
let screenHeight </span>= Dimensions.get('window'<span style="color: rgba(0, 0, 0, 1)">).height;
console.log(screenWidth</span>+" "+screenHeight+"带有小数"<span style="color: rgba(0, 0, 0, 1)">);
export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> class App extends React.Component{
constructor(props){
super(props);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.changePausedState = <span style="color: rgba(0, 0, 255, 1)">this</span>.changePausedState.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.customerSliderValue = <span style="color: rgba(0, 0, 255, 1)">this</span>.customerSliderValue.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.enterFullScreen = <span style="color: rgba(0, 0, 255, 1)">this</span>.enterFullScreen.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>._changePauseSliderFullState = <span style="color: rgba(0, 0, 255, 1)">this</span>._changePauseSliderFullState.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>._onStartShouldSetResponder = <span style="color: rgba(0, 0, 255, 1)">this</span>._onStartShouldSetResponder.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.state =<span style="color: rgba(0, 0, 0, 1)"> {
isPaused: </span><span style="color: rgba(0, 0, 255, 1)">true</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是暂停</span>
duration: 0, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">总时长</span>
currentTime: 0, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前播放时间</span>
sliderValue: 0, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">进度条的进度 </span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用来控制进入全屏的属性</span>
<span style="color: rgba(0, 0, 0, 1)"> videoWidth: screenWidth,
videoHeight: </span>226<span style="color: rgba(0, 0, 0, 1)">,
isFullScreen: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
isVisiblePausedSliderFullScreen: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
}
changePausedState(){ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">控制按钮显示播放,要显示进度条3秒钟,之后关闭显示</span>
<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
isPaused: </span><span style="color: rgba(0, 0, 255, 1)">this</span>.state.isPaused?<span style="color: rgba(0, 0, 255, 1)">false</span>:<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
isVisiblePausedSliderFullScreen: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个定时调用失去了this指向</span>
let that = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
setTimeout(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
that.setState({
isVisiblePausedSliderFullScreen: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
})
},</span>3000<span style="color: rgba(0, 0, 0, 1)">)
}
_changePauseSliderFullState(){ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 单击事件,是否显示 “暂停、进度条、全屏按钮 盒子”</span>
let flag = <span style="color: rgba(0, 0, 255, 1)">this</span>.state.isVisiblePausedSliderFullScreen?<span style="color: rgba(0, 0, 255, 1)">false</span>:<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
isVisiblePausedSliderFullScreen: flag
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个定时调用失去了this指向</span>
let that = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
setTimeout(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
that.setState({
isVisiblePausedSliderFullScreen: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
})
},</span>3000<span style="color: rgba(0, 0, 0, 1)">)
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">格式化音乐播放的时间为0:00。借助onProgress的定时器调用,更新当前时间</span>
<span style="color: rgba(0, 0, 0, 1)"> formatMediaTime(time) {
let minute </span>= Math.floor(time / 60<span style="color: rgba(0, 0, 0, 1)">);
let second </span>= parseInt(time - minute * 60<span style="color: rgba(0, 0, 0, 1)">);
minute </span>= minute >= 10 ? minute : "0" +<span style="color: rgba(0, 0, 0, 1)"> minute;
second </span>= second >= 10 ? second : "0" +<span style="color: rgba(0, 0, 0, 1)"> second;
</span><span style="color: rgba(0, 0, 255, 1)">return</span> minute + ":" +<span style="color: rgba(0, 0, 0, 1)"> second;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">加载视频调用,主要是拿到 “总时间”,并格式化</span>
<span style="color: rgba(0, 0, 0, 1)"> customerOnload(e){
let time </span>=<span style="color: rgba(0, 0, 0, 1)"> e.duration;
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
duration: time
})
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获得当前的,播放时间数,但这个数是0.104,需要处理</span>
<span style="color: rgba(0, 0, 0, 1)"> customerOnprogress(e){
let time </span>= e.currentTime; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取播放视频的秒数 </span>
<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
currentTime: time,
sliderValue: time
})
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 移动滑块,改变视频播放进度</span>
<span style="color: rgba(0, 0, 0, 1)"> customerSliderValue(value){
</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.player.seek(value);
}
enterFullScreen(){ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1.改变宽高2.允许进入全屏模式3.如何配置屏幕旋转,不需要改变进度条盒子的显示和隐藏</span>
<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.setState({
videoWidth: screenHeight,
videoHeight: screenWidth,
isFullScreen: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 直接设置方向</span>
<span style="color: rgba(0, 0, 0, 1)"> Orientation.lockToLandscape();
}
_onStartShouldSetResponder(e){
console.log(e);
}
componentDidMount() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> initial =<span style="color: rgba(0, 0, 0, 1)"> Orientation.getInitialOrientation();
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (initial === 'PORTRAIT'<span style="color: rgba(0, 0, 0, 1)">) {
console.log(</span>'是竖屏'<span style="color: rgba(0, 0, 0, 1)">);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
console.log(</span>'如果是横屏,就将其旋转过来'<span style="color: rgba(0, 0, 0, 1)">);
Orientation.lockToPortrait();
}
}
render(){
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 播放按钮组件:是否显示</span>
let playButtonComponent =<span style="color: rgba(0, 0, 0, 1)"> (
</span><<span style="color: rgba(0, 0, 0, 1)">TouchableWithoutFeedback
onPress</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.changePausedState}
</span>>
<View style={styles.playBtn}>
</View>
</TouchableWithoutFeedback>
<span style="color: rgba(0, 0, 0, 1)"> );
let pausedBtn </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.state.isPaused?playButtonComponent:<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 暂停按钮、进度条、全屏按钮 是否显示</span>
let pausedSliderFullComponent =<span style="color: rgba(0, 0, 0, 1)"> (
</span><View style={{position:"absolute",bottom:0}}>
<View style={{flexDirection:'row',alignItems:'center'}}><span style="color: rgba(0, 0, 0, 1)">
{</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 进度条按钮 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
</span><View style={styles.sliderBox}>
<Text>{<span style="color: rgba(0, 0, 255, 1)">this</span>.formatMediaTime(<span style="color: rgba(0, 0, 255, 1)">this</span>.state.currentTime)}</Text>
<<span style="color: rgba(0, 0, 0, 1)">Slider
style</span>={{width: 200, height: 40<span style="color: rgba(0, 0, 0, 1)">}}
value</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state.sliderValue}
maximumValue</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state.duration}
thumbTintColor</span>="#000" <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">开关夹点的yanse </span>
minimumTrackTintColor="red"<span style="color: rgba(0, 0, 0, 1)">
maximumTrackTintColor</span>="#ccc"<span style="color: rgba(0, 0, 0, 1)">
step</span>={1<span style="color: rgba(0, 0, 0, 1)">}
onValueChange</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.customerSliderValue}
</span>/>
<Text>{<span style="color: rgba(0, 0, 255, 1)">this</span>.formatMediaTime(<span style="color: rgba(0, 0, 255, 1)">this</span>.state.duration)}</Text>
</View>
{<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 全屏按钮 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
</span><View>
<<span style="color: rgba(0, 0, 0, 1)">TouchableOpacity
onPress</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.enterFullScreen}
</span>>
<Text style={{backgroundColor:'#00ff00',padding:5}}>全屏</Text>
</TouchableOpacity>
</View>
</View>
</View>
<span style="color: rgba(0, 0, 0, 1)"> );
let pausedSliderFull </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>.state.isVisiblePausedSliderFullScreen?pausedSliderFullComponent:<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
</span><View>
<View>
<<span style="color: rgba(0, 0, 0, 1)">TouchableWithoutFeedback
onPress</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._changePauseSliderFullState}
onResponderMove</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">._onStartShouldSetResponder}
</span>>
<Video source={require('../jifen.mp4'<span style="color: rgba(0, 0, 0, 1)">)}
ref</span>={(ref) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.player =<span style="color: rgba(0, 0, 0, 1)"> ref
}}
style</span>={{width: <span style="color: rgba(0, 0, 255, 1)">this</span>.state.videoWidth,height: <span style="color: rgba(0, 0, 255, 1)">this</span>.state.videoHeight,backgroundColor:"#FFC1C1"<span style="color: rgba(0, 0, 0, 1)">}}
allowsExternalPlayback</span>={<span style="color: rgba(0, 0, 255, 1)">false</span>} <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 不允许导出 或 其他播放器播放</span>
paused = {<span style="color: rgba(0, 0, 255, 1)">this</span>.state.isPaused} <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 控制视频是否播放</span>
resizeMode="cover"<span style="color: rgba(0, 0, 0, 1)">
onLoad</span>={(e)=><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.customerOnload(e)}
onProgress</span>={(e)=><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.customerOnprogress(e)}
fullscreen</span>={<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state.isFullScreen}
</span>/>
</TouchableWithoutFeedback>
{<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 播放的按钮:点击之后需要消失 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
{pausedBtn}
{</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> 暂停按钮,进度条,全屏按钮 </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
{pausedSliderFull}
</span></View>
</View>
<span style="color: rgba(0, 0, 0, 1)"> )
}
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> styles =<span style="color: rgba(0, 0, 0, 1)"> StyleSheet.create({
myVideo:{
width: </span>340<span style="color: rgba(0, 0, 0, 1)">,
height: </span>240<span style="color: rgba(0, 0, 0, 1)">
},
playBtn:{
width: </span>50<span style="color: rgba(0, 0, 0, 1)">,
height: </span>50<span style="color: rgba(0, 0, 0, 1)">,
backgroundColor:</span>'red'<span style="color: rgba(0, 0, 0, 1)">,
borderRadius: </span>50<span style="color: rgba(0, 0, 0, 1)">,
position: </span>"absolute"<span style="color: rgba(0, 0, 0, 1)">,
top: </span>"50%"<span style="color: rgba(0, 0, 0, 1)">,
left: </span>"50%"<span style="color: rgba(0, 0, 0, 1)">,
marginLeft: </span>-25<span style="color: rgba(0, 0, 0, 1)">,
marginTop:</span>-25<span style="color: rgba(0, 0, 0, 1)">,
zIndex:</span>999<span style="color: rgba(0, 0, 0, 1)">
},
sliderBox:{
flex:</span>0<span style="color: rgba(0, 0, 0, 1)">,
flexDirection:</span>'row'<span style="color: rgba(0, 0, 0, 1)">,
alignItems:</span>'center'<span style="color: rgba(0, 0, 0, 1)">
}
});</span></pre>
</div>
<p><br><br><strong>看个效果图吧,这个普通播放时</strong></p>
<p><img src="https://img2018.cnblogs.com/i-beta/1723157/201912/1723157-20191212175257104-63532089.png"><br><br><strong>这是全屏播放时</strong><br><img src="https://img2018.cnblogs.com/i-beta/1723157/201912/1723157-20191212175448950-1836292606.png"></p>
<p> </p>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)">测试这个花了挺长时间的,有用点个赞吧,哈哈</span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><img src="https://img2020.cnblogs.com/blog/1723157/202008/1723157-20200827103511251-953043896.png"></span></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/tengyuxin/p/12030742.html
頁:
[1]