react-native 封装 VedioPlayer 组件
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 组件的更多相关文章
- react native 封装TextInput组件
上一篇 react-native文章提到了TextInput组件对安卓的适配问题,因此对该组件进行封装很有必要. 文章地址 react native定报预披项目知识点总结 TextInput介绍 官 ...
- react native之组织组件
这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...
- React Native之倒计时组件的实现(ios android)
React Native之倒计时组件的实现(ios android) 一,需求分析 1,app需实现类似于淘宝的活动倒计时,并在倒计时结束时,活动也结束. 2,实现订单倒计时,并在倒计时结束时,订单关 ...
- React Native封装Toast与加载Loading组件
React Native开发封装Toast与加载Loading组件 在App开发中,我们避免不了使用的两个组件,一个Toast,一个网络加载Loading,在RN开发中,也是一样,React Nati ...
- react native 之子组件和父组件之间的通信
react native开发中,为了封装性经常需要自定义组件,这样就会出现父组件和子组件,那么怎么在父组件和子组件之间相互通信呢,也就是怎么在各自界面push和pop.传值. 父组件传递给子组件: 父 ...
- React Native常用第三方组件汇总--史上最全 之一
React Native 项目常用第三方组件汇总: react-native-animatable 动画 react-native-carousel 轮播 react-native-countdown ...
- React Native常用第三方组件汇总--史上最全[转]
本文出处: http://blog.csdn.net/chichengjunma/article/details/52920137 React Native 项目常用第三方组件汇总: react-na ...
- React Native知识6-NavigatorIOS组件
NavigatorIOS包装了UIKit的导航功能,可以使用左划功能来返回到上一界面.本组件并非由Facebook官方开发组维护.这一组件的开发完全由社区主导.如果纯js的方案能够满足你的需求的话,那 ...
- React Native知识2-Text组件
Text用于显示文本的React组件,并且它也支持嵌套.样式,以及触摸处理.在下面的例子里,嵌套的标题和正文文字会继承来自styles.baseText的fontFamily字体样式,不过标题上还附加 ...
- React Native 系列(五) -- 组件间传值
前言 本系列是基于React Native版本号0.44.3写的.任何一款 App 都有界面之间数据传递的这个步骤的,那么在RN中,组件间是怎么传值的呢?这篇文章将介绍到顺传.逆传已经通过通知传值. ...
随机推荐
- [置顶] Linux Malloc分析-从用户空间到内核空间【转】
转自:http://blog.csdn.net/ordeder/article/details/41654509 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...
- Linux驱动修炼之道-SPI驱动框架源码分析(上)【转】
转自:http://blog.csdn.net/lanmanck/article/details/6895318 SPI驱动架构,以前用过,不过没这个详细,跟各位一起分享: 来自:http://blo ...
- ios 最新系统bug与解决——微信公众号中弹出键盘再收起时,原虚拟键盘位点击事件无效
最近ios发布新版本系统12.1,随着部分用户的系统更新,一些问题也渐渐暴露出来... 公司用户反映微信公众号出现了点击无效的bug!!测试调查发现,只有iphonex.iphone6,ihpone7 ...
- zabbix 硬盘健康监控
#!/bin/sh function sh { sd=`ls /dev/ | grep '^sd' |grep -v '[0-9]$'` echo '' > /usr/local/zabbix/ ...
- c语言自动对齐原则
转载一篇博客: http://blog.csdn.net/hairetz/article/details/4084088 1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员, ...
- [BZOJ4760][Usaco2017 Jan]Hoof, Paper, Scissors dp
4760: [Usaco2017 Jan]Hoof, Paper, Scissors Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 136 Solv ...
- PL/SQL&存储过程||存储函数&触发器
plsql 有点:交互式 非过程化 数据操纵能力强 自动导航语句简单 调试简单 想率高 声明类型的方式 1.基本类型 2.引用变量 3.记录型变量 基本格式 declare 声明 b ...
- JDBC二部曲之_事物、连接池
事务 事务概述 事务的四大特性(ACID) 事务的四大特性是: l 原子性(Atomicity):事务中所有操作是不可再分割的原子单位.事务中所有操作要么全部执行成功,要么全部执行失败. l 一致 ...
- [HDU6240]Server
题目大意: 用$n$条线段覆盖区间$[1,t]$上的整点.每条线段有4个属性$(S_i,T_i,A_i,B_i)$,表示用第$i$条线段可以覆盖区间$[S_i,T_i]$.若选取线段的集合为$S$,最 ...
- unity3d 场景配置文件生成代码
using UnityEngine; using UnityEditor; using System.IO; using System; using System.Text; using System ...