RN 写一个视频播放器

目标需求:
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

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'
    }
  });



看个效果图吧,这个普通播放时



这是全屏播放时

测试这个花了挺长时间的,有用点个赞吧,哈哈

猜你喜欢

转载自www.cnblogs.com/tengyuxin/p/12030742.html
RN