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={{ 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={{ 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:{ 340, height: 240 }, playBtn:{ 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' } });
看个效果图吧,这个普通播放时
这是全屏播放时
测试这个花了挺长时间的,有用点个赞吧,哈哈