鄙视基本盘 發表於 2019-12-12 17:56:00

RN 使用react-native-video 播放视频(包含进度条、全屏)

<p><span style="font-size: 18px">21年12月3日,阐述上有问题:应该将问题拆分,不该将代码整一大堆,看着很不舒适</span></p>
<p>&nbsp;</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>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>需要三个组件</p>
<p>1. 播放视频组件, react-native-video&nbsp; &nbsp; 官网地址&nbsp;https://www.npmjs.com/package/react-native-video#allowsexternalplayback<br></p>
<p>2. 进度条,官网上提供的 slider组件我忘记说的什么原因,即将停止支持,我找了<strong>react-native-silder</strong>&nbsp; 这个个第三方包 官网地址&nbsp;&nbsp;https://github.com/react-native-community/react-native-slider#onvaluechange<br>现在<strong>react-native-silder</strong>&nbsp;的一些生命周期方法都是警告,因为react很多声明周期函数,已经废弃或改名字 ,我目前在尝试&nbsp; &nbsp;https://github.com/callstack/react-native-slider</p>
<p>3. 全屏播放,react-native-orientation这个包有问题,因为RN 将对 rnpm 换一种支持策略 ,所以选择用 <strong>react-native-orientation-locker</strong> 官网地址&nbsp;&nbsp;https://github.com/wonday/react-native-orientation-locker</p>
<p>&nbsp;</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 &gt;= 10 ? minute : "0" +<span style="color: rgba(0, 0, 0, 1)"> minute;
      second </span>= second &gt;= 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>&lt;<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>&gt;
                &lt;View style={styles.playBtn}&gt;                     
                &lt;/View&gt;
            &lt;/TouchableWithoutFeedback&gt;
<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>&lt;View style={{position:"absolute",bottom:0}}&gt;
                &lt;View style={{flexDirection:'row',alignItems:'center'}}&gt;<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>&lt;View style={styles.sliderBox}&gt;
                        &lt;Text&gt;{<span style="color: rgba(0, 0, 255, 1)">this</span>.formatMediaTime(<span style="color: rgba(0, 0, 255, 1)">this</span>.state.currentTime)}&lt;/Text&gt;
                        &lt;<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>/&gt;
                        &lt;Text&gt;{<span style="color: rgba(0, 0, 255, 1)">this</span>.formatMediaTime(<span style="color: rgba(0, 0, 255, 1)">this</span>.state.duration)}&lt;/Text&gt;
                  &lt;/View&gt;
                  {<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>&lt;View&gt;
                        &lt;<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>&gt;                           
                            &lt;Text style={{backgroundColor:'#00ff00',padding:5}}&gt;全屏&lt;/Text&gt;                     
                        &lt;/TouchableOpacity&gt;
                  &lt;/View&gt;
               
            
                &lt;/View&gt;   
            &lt;/View&gt;
<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>&lt;View&gt;
                &lt;View&gt;
                  &lt;<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>&gt;
                        &lt;Video source={require('../jifen.mp4'<span style="color: rgba(0, 0, 0, 1)">)}
                            ref</span>={(ref) =&gt;<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)=&gt;<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.customerOnload(e)}
                            onProgress</span>={(e)=&gt;<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>/&gt;
                  &lt;/TouchableWithoutFeedback&gt;
                  {<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>&lt;/View&gt;
&lt;/View&gt;
<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>&nbsp;</p>
<p>&nbsp;</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>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/tengyuxin/p/12030742.html
頁: [1]
查看完整版本: RN 使用react-native-video 播放视频(包含进度条、全屏)