1.封装组件

src/components/VideoPlayer/index.js

/**
* 视频播放器 组件(VideoPlayer)
*/
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
Dimensions,
ActivityIndicator,
TouchableOpacity,
} from 'react-native';
// 播放器组件
import Video from 'react-native-video';
import Icon from 'react-native-vector-icons/Ionicons'; let {width} = Dimensions.get("window"); export default class VideoPlayer extends Component {
constructor(props) {
super(props);
this.state = {
// 视频播放器
rate: 1, // 是否暂停 0:暂停, 1:正常
muted: false, // 是否静音
resizeMode: 'contain', // 充满整个播放区域 cover 或 自适应 contain
repeat: false, // 是否重复播放 // video control
videoOk: true, // 视频是否出错
videoLoaded: false, // 视频是否加载
playing: false, // 视频是否播放中
paused: false, // 是否暂停
videoProgress: 0.01, // 进度条 // all time
videoTotal: 0, // 视频总时间
currentTime: 0, // 当前时间
}
} render() {
return (
<View style={styles.videoBox}>
<Video
style={styles.video}
ref="videoPlayer"
source={{uri: this.props.uri}}
// 声音放大的倍数: 0 is muted, 1 is double.
volume={5}
// 是否暂停 true or false.
paused={this.state.paused}
// 0 是 暂停, 1 是 正常.
rate={this.state.rate}
// 是否静音 true or false.
muted={this.state.muted}
// 充满整个播放区域 或 自适应
resizeMode={this.state.resizeMode}
// 是否重复播放 true or false.
repeat={this.state.repeat}
// 当视频开始加载时
onLoadStart={this._onLoadStart.bind(this)}
// 当视频在不断的加载时
onLoad={this._onLoad.bind(this)}
// 当视频播放时,每250ms调用一次,便于知悉当前播放位置(时间)
onProgress={this._onProgress.bind(this)}
// 当视频播放结束时调用
onEnd={this._onEnd.bind(this)}
// 当视频出错时调用
onError={this._onError.bind(this)}
/>
{/* 视频出错 */}
{
!this.state.videoOk && <Text style={styles.failText}>视频出错了!很抱歉</Text>
} {/* 没有加载 */}
{
!this.state.videoLoaded && <ActivityIndicator style={styles.loading} color="#ee735c"/>
} {/* 播放结束 */}
{
this.state.videoLoaded && !this.state.playing
?
<Icon
style={styles.playIcon}
onPress={this._rePlay.bind(this)}
name='ios-play'
size={48}
/>
: null
} {/* 视频正在播放,控制是否暂停 */}
{
this.state.videoLoaded && this.state.playing
?
<TouchableOpacity
style={styles.pauseBtn}
onPress={this._pause.bind(this)}
>
{
this.state.paused
?
<Icon
style={styles.resumeIcon}
size={48}
onPress={this._resume.bind(this)}
name="ios-play"
/>
:
<Text></Text>
}
</TouchableOpacity>
: null
}
{/*进度条*/}
<View style={styles.progressBox}>
<View style={[styles.progressBar, {width: width * this.state.videoProgress}]}></View>
</View>
</View>
)
} // 当视频开始加载时
_onLoadStart() {
//
} // 当视频在不断的加载时
_onLoad() {
//
} // 当视频播放时,每250ms调用一次,便于知悉当前播放位置(时间)
_onProgress(data) {
if (!this.state.videoLoaded) {
this.setState({
videoLoaded: true
})
} // 视频中时长
let duration = data.playableDuration;
let currentTime = data.currentTime;
// toFixed(2) get 小数点后两位
let percent = Number((currentTime / duration).toFixed(2));
let newState = {
videoTotal: duration,
currentTime: Number(data.currentTime.toFixed(2)),
videoProgress: percent
}; if (!this.state.videoLoaded) {
newState.videoLoaded = true
}
// 视频暂停播放或播放结束,显示播放按钮
if (!this.state.playing) {
newState.playing = true
} this.setState(newState);
} // 当视频播放结束时调用
_onEnd() {
this.setState({
videoProgress: 1, // 进度为1表示播放结束
playing: false
});
} // 当视频出错时调用
_onError(e) {
this.setState({
videoOk: false
});
} // 重新播放
_rePlay() {
this.refs.videoPlayer.seek(0)
} // 暂停播放
_pause() {
if (!this.state.paused) {
this.setState({
paused: true
})
}
} // 继续播放
_resume() {
if (this.state.paused) {
this.setState({
paused: false
})
}
}
} const styles = StyleSheet.create({
// 视频播放器 容器
videoBox: {
width: width,
height: width * 0.56,
backgroundColor: '#000'
},
// 视频播放器
video: {
width: width,
height: width * 0.56,
backgroundColor: '#000'
},
// 加载动画(菊花图)
loading: {
position: 'absolute',
left: 0,
top: 80,
width: width,
alignSelf: 'center', // 字体居中对齐
backgroundColor: 'transparent'
},
// 视频出错时,文本样式
failText: {
position: 'absolute',
left: 0,
top: 90,
width: width,
textAlign: 'center',
color: '#fff',
backgroundColor: 'transparent'
},
// 进度条样式
progressBox: {
width: width,
height: 2,
backgroundColor: '#ccc'
}, progressBar: {
width: 1,
height: 2,
backgroundColor: '#ff6600'
},
// 播放按钮样式
playIcon: {
position: 'absolute',
top: 90,
left: width / 2 - 30,
width: 60,
height: 60,
paddingTop: 8,
paddingLeft: 22,
backgroundColor: 'transparent',
borderColor: '#fff',
borderWidth: 1,
borderRadius: 30,
color: '#ed7b66'
},
// 暂停
pauseBtn: {
position: 'absolute',
left: 0,
top: 0,
width: width,
height: width * 0.56
},
// 继续
resumeIcon: {
position: 'absolute',
top: 80,
left: width / 2 - 30,
width: 60,
height: 60,
paddingTop: 8,
paddingLeft: 22,
backgroundColor: 'transparent',
borderColor: '#fff',
borderWidth: 1,
borderRadius: 30,
color: '#ed7b66'
}
});

2.调用组件

{/*视频播放器*/}
<VideoPlayer uri={data.video} />

3.效果图

react-native 封装 VedioPlayer 组件的更多相关文章

  1. react native 封装TextInput组件

    上一篇 react-native文章提到了TextInput组件对安卓的适配问题,因此对该组件进行封装很有必要. 文章地址  react native定报预披项目知识点总结 TextInput介绍 官 ...

  2. react native之组织组件

    这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...

  3. React Native之倒计时组件的实现(ios android)

    React Native之倒计时组件的实现(ios android) 一,需求分析 1,app需实现类似于淘宝的活动倒计时,并在倒计时结束时,活动也结束. 2,实现订单倒计时,并在倒计时结束时,订单关 ...

  4. React Native封装Toast与加载Loading组件

    React Native开发封装Toast与加载Loading组件 在App开发中,我们避免不了使用的两个组件,一个Toast,一个网络加载Loading,在RN开发中,也是一样,React Nati ...

  5. react native 之子组件和父组件之间的通信

    react native开发中,为了封装性经常需要自定义组件,这样就会出现父组件和子组件,那么怎么在父组件和子组件之间相互通信呢,也就是怎么在各自界面push和pop.传值. 父组件传递给子组件: 父 ...

  6. React Native常用第三方组件汇总--史上最全 之一

    React Native 项目常用第三方组件汇总: react-native-animatable 动画 react-native-carousel 轮播 react-native-countdown ...

  7. React Native常用第三方组件汇总--史上最全[转]

    本文出处: http://blog.csdn.net/chichengjunma/article/details/52920137 React Native 项目常用第三方组件汇总: react-na ...

  8. React Native知识6-NavigatorIOS组件

    NavigatorIOS包装了UIKit的导航功能,可以使用左划功能来返回到上一界面.本组件并非由Facebook官方开发组维护.这一组件的开发完全由社区主导.如果纯js的方案能够满足你的需求的话,那 ...

  9. React Native知识2-Text组件

    Text用于显示文本的React组件,并且它也支持嵌套.样式,以及触摸处理.在下面的例子里,嵌套的标题和正文文字会继承来自styles.baseText的fontFamily字体样式,不过标题上还附加 ...

  10. React Native 系列(五) -- 组件间传值

    前言 本系列是基于React Native版本号0.44.3写的.任何一款 App 都有界面之间数据传递的这个步骤的,那么在RN中,组件间是怎么传值的呢?这篇文章将介绍到顺传.逆传已经通过通知传值. ...

随机推荐

  1. 调用SMTP发送有附件的邮件

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  2. 使用QML创建界面(转)

    原文转自 https://blog.csdn.net/rl529014/article/details/51378307 在Qt编程中,我们可以使用纯C++代码,或C++和XML结合的方式来创建GUI ...

  3. Opengl场景中加光照包含几个步骤

    http://zuoye.baidu.com/question/44e2a82d7ad5c0e1d33ddb9a40e0bf86.html  Opengl场景中加光照包含几个步骤,各个步骤实现用的函数 ...

  4. 《Linux命令、编辑器与shell编程》第三版 学习笔记---001

    Linux概述 1.具有内核编程接口 2.支持多用户(同时) 3.支持多任务 4.支持安全的分层文件系统 a.标准 b.链接 c.权限 5.shell(命令解释器和编程语言) a.文件名生成(通配符和 ...

  5. Java进阶之路,技术要点

    宏观方面 一.JAVA.要想成为JAVA(高级)工程师肯定要学习JAVA.一般的程序员或许只需知道一些JAVA的语法结构就可以应付了.但要成为JAVA(高级)工程师,您要对JAVA做比较深入的研究.您 ...

  6. vagrant virtualbox VM inaccessible解决办法

    vagrant无法访问的提示:Please open VirtualBox and clear out your inaccessible virtual machines or find a way ...

  7. 基于SpringMVC的上传文件实现

    基于SpringMVC的上传文件实现 1.项目源码 源码地址:upload 2.关键代码 @RequestMapping("/upload2") public void datal ...

  8. (1)oracle安装、卸载、启动、关闭、登陆以及同时遇到的问题

    数据库概念 在oracle里数据库是一个静态的概念,数据库的资料保存在硬盘上,一个数据库可以有多个实例 数据库实例 数据库实例是一个动态的概念,它是进程+这个进程的内存块.就把它当成个指针吧,这个指针 ...

  9. 洛谷——2722总分 Score Inflation

    题目背景 学生在我们USACO的竞赛中的得分越多我们越高兴. 我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助 题目描述 我们可以从几个种类中选取竞赛的题目,这里的一个"种类& ...

  10. 可持久化线段树(主席树)(图文并茂详解)【poj2104】【区间第k大】

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63740442 向大(hei)佬(e)实力学(di ...