RN 使用react-native-video 播放視頻(包含進度條、全屏)
21年12月3日,闡述上有問題:應該將問題拆分,不該將代碼整一大堆,看著很不舒適
目標需求:
1. 實現視頻播放
2. 進度條
3. 進入全屏
目標圖是這樣的:
需要三個組件
1. 播放視頻組件, react-native-video 官網地址 https://www.npmjs.com/package/react-native-video#allowsexternalplayback
2. 進度條,官網上提供的 slider組件我忘記說的什么原因,即將停止支持,我找了react-native-silder 這個個第三方包 官網地址 https://github.com/react-native-community/react-native-slider#onvaluechange
現在react-native-silder 的一些生命周期方法都是警告,因為react很多聲明周期函數,已經廢棄或改名字 ,我目前在嘗試 https://github.com/callstack/react-native-slider
3. 全屏播放,react-native-orientation這個包有問題,因為RN 將對 rnpm 換一種支持策略 ,所以選擇用 react-native-orientation-locker 官網地址 https://github.com/wonday/react-native-orientation-locker
后面的就直接上代碼了
import React from 'react'; import {View,Text,StyleSheet,TouchableWithoutFeedback,TouchableOpacity,Dimensions} from 'react-native'; //導入Video組件 import Video from 'react-native-video'; // 導入 Silder組件 import Slider from '@react-native-community/slider'; // 屏幕方向鎖定: 他需要改變 原來Android文件代碼,當然適配兩端的話,IOS也是需要更改的。 import Orientation from 'react-native-orientation-locker'; let screenWidth = Dimensions.get('window').width; let screenHeight = Dimensions.get('window').height; console.log(screenWidth+" "+screenHeight+"帶有小數"); export default class App extends React.Component{ constructor(props){ super(props); this.changePausedState = this.changePausedState.bind(this); this.customerSliderValue = this.customerSliderValue.bind(this); this.enterFullScreen = this.enterFullScreen.bind(this); this._changePauseSliderFullState = this._changePauseSliderFullState.bind(this); this._onStartShouldSetResponder = this._onStartShouldSetResponder.bind(this); this.state = { isPaused: true, //是暫停 duration: 0, //總時長 currentTime: 0, //當前播放時間 sliderValue: 0, //進度條的進度 //用來控制進入全屏的屬性 videoWidth: screenWidth, videoHeight: 226, isFullScreen: false, isVisiblePausedSliderFullScreen: false } } changePausedState(){ //控制按鈕顯示播放,要顯示進度條3秒鐘,之后關閉顯示 this.setState({ isPaused: this.state.isPaused?false:true, isVisiblePausedSliderFullScreen: true }) //這個定時調用失去了this指向 let that = this; setTimeout(function(){ that.setState({ isVisiblePausedSliderFullScreen: false }) },3000) } _changePauseSliderFullState(){ // 單擊事件,是否顯示 “暫停、進度條、全屏按鈕 盒子” let flag = this.state.isVisiblePausedSliderFullScreen?false:true; this.setState({ isVisiblePausedSliderFullScreen: flag }) //這個定時調用失去了this指向 let that = this; setTimeout(function(){ that.setState({ isVisiblePausedSliderFullScreen: false }) },3000) } //格式化音樂播放的時間為0:00。借助onProgress的定時器調用,更新當前時間 formatMediaTime(time) { let minute = Math.floor(time / 60); let second = parseInt(time - minute * 60); minute = minute >= 10 ? minute : "0" + minute; second = second >= 10 ? second : "0" + second; return minute + ":" + second; } //加載視頻調用,主要是拿到 “總時間”,并格式化 customerOnload(e){ let time = e.duration; this.setState({ duration: time }) } // 獲得當前的,播放時間數,但這個數是0.104,需要處理 customerOnprogress(e){ let time = e.currentTime; // 獲取播放視頻的秒數 this.setState({ currentTime: time, sliderValue: time }) } // 移動滑塊,改變視頻播放進度 customerSliderValue(value){ this.player.seek(value); } enterFullScreen(){ //1.改變寬高 2.允許進入全屏模式 3.如何配置屏幕旋轉,不需要改變進度條盒子的顯示和隱藏 this.setState({ videoWidth: screenHeight, videoHeight: screenWidth, isFullScreen: true }) // 直接設置方向 Orientation.lockToLandscape(); } _onStartShouldSetResponder(e){ console.log(e); } componentDidMount() { var initial = Orientation.getInitialOrientation(); if (initial === 'PORTRAIT') { console.log('是豎屏'); } else { console.log('如果是橫屏,就將其旋轉過來'); Orientation.lockToPortrait(); } } render(){ // 播放按鈕組件:是否顯示 let playButtonComponent = ( <TouchableWithoutFeedback onPress={this.changePausedState} > <View style={styles.playBtn}> </View> </TouchableWithoutFeedback> ); let pausedBtn = this.state.isPaused?playButtonComponent:null; // 暫停按鈕、進度條、全屏按鈕 是否顯示 let pausedSliderFullComponent = ( <View style={{position:"absolute",bottom:0}}> <View style={{flexDirection:'row',alignItems:'center'}}> {/* 進度條按鈕 */} <View style={styles.sliderBox}> <Text>{this.formatMediaTime(this.state.currentTime)}</Text> <Slider style={{width: 200, height: 40}} value={this.state.sliderValue} maximumValue={this.state.duration} thumbTintColor="#000" //開關夾點的yanse minimumTrackTintColor="red" maximumTrackTintColor="#ccc" step={1} onValueChange={this.customerSliderValue} /> <Text>{this.formatMediaTime(this.state.duration)}</Text> </View> {/* 全屏按鈕 */} <View> <TouchableOpacity onPress={this.enterFullScreen} > <Text style={{backgroundColor:'#00ff00',padding:5}}>全屏</Text> </TouchableOpacity> </View> </View> </View> ); let pausedSliderFull = this.state.isVisiblePausedSliderFullScreen?pausedSliderFullComponent:null; return ( <View> <View> <TouchableWithoutFeedback onPress={this._changePauseSliderFullState} onResponderMove={this._onStartShouldSetResponder} > <Video source={require('../jifen.mp4')} ref={(ref) => { this.player = ref }} style={{width: this.state.videoWidth,height: this.state.videoHeight,backgroundColor:"#FFC1C1"}} allowsExternalPlayback={false} // 不允許導出 或 其他播放器播放 paused = {this.state.isPaused} // 控制視頻是否播放 resizeMode="cover" onLoad={(e)=>this.customerOnload(e)} onProgress={(e)=>this.customerOnprogress(e)} fullscreen={this.state.isFullScreen} /> </TouchableWithoutFeedback> {/* 播放的按鈕:點擊之后需要消失 */} {pausedBtn} {/* 暫停按鈕,進度條,全屏按鈕 */} {pausedSliderFull} </View> </View> ) } } var styles = StyleSheet.create({ myVideo:{ width: 340, height: 240 }, playBtn:{ width: 50, height: 50, backgroundColor:'red', borderRadius: 50, position: "absolute", top: "50%", left: "50%", marginLeft: -25, marginTop:-25, zIndex:999 }, sliderBox:{ flex:0, flexDirection:'row', alignItems:'center' } });
看個效果圖吧,這個普通播放時

這是全屏播放時
測試這個花了挺長時間的,有用點個贊吧,哈哈


浙公網安備 33010602011771號