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中,组件间是怎么传值的呢?这篇文章将介绍到顺传.逆传已经通过通知传值. ...
随机推荐
- 【IDEA】IDEA中部署的项目添加Tomcat自带的一些项目
在IDEA部署项目的时候发现没有tomcat自带的一些项目,有时候我们需要tomcat自带的项目查看一些配置的信息,经过查阅资料后做记录如下: 1.在Eclipse中点击Run ->Edit C ...
- JS操作checkBox
代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w ...
- error LNK2001: 无法解析的外部符号 "public: virtual long __stdcall CBaseFilter(转)
原文转自 https://www.cnblogs.com/xiongjiaji/archive/2010/12/31/2476565.html 今天用VS2005编译DirectShow程序,发现出来 ...
- 在cocos2d中实现真正意思上的图片放大和缩小
http://www.cnblogs.com/dinghing154/archive/2012/08/05/2623970.html 在编写程序的时候我们常常使用self.scale来让我们使用的图片 ...
- 在floodlight源码的基础上添加一个新的module并正确运行
1.在src/main/java目录下新建一个package,目录结构如下: 2.在新建的package下,新建一个class,名字就是自定义的module,接下来implements想实现的serv ...
- AC日记——[WC2013]糖果公园 cogs 1817
[WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...
- vs code 在windows10 64bit系统配置python开发环境
一.搭建 python 环境 在 VSC 中点击 F1 键,弹出控制台,输入 ext install 界面左侧弹出扩展窗格,输入python,确认,开始搜索下载发布者为Don Jayamanne 的 ...
- 整数划分问题(记忆化搜索和DP方法)
一. 问题 现在有一正整数N,要把它分为若干正整数之和,问有多少种本质不同的分法? (1)其中最大数不超过m, 有多少种分法? (2)分割后的正整数的数目不超过m个, 有多少种分法? (3)分成最大数 ...
- 洛谷——1164 小A点菜(背包方案数)
大水题!! 题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过uim由于买 ...
- sqlldr control file compare with HEX value
when field= UTL_I18N.RAW_TO_CHAR ('e38080', 'AL32UTF8')