这篇文章主要跟大家分享一个视频播放的react-native的工具,以及不是使用Orientation库,进行控制视频播放
效果如下:
[链接](https://s23.aconvert.com/convert/p3r68-cdx67/9w9i3-vht6k.gif](https://s23.aconvert.com/convert/p3r68-cdx67/9w9i3-vht6k.gif)
1,集成react-native-video
传送门https://github.com/react-native-community/react-native-video#ios-app-transport-security
npm install --save react-native-video
react-native link react-native-video
2,封装播放组件
针对于播放组件
定义变量:
state = {
data: {},
videoUrl:
"http://124.129.157.208:8810/SD/2017qingdao/xiaoxueEnglish/grade3/b/1.mp4",
videoCover:
"http://124.129.157.208:8889/data/uploads/kecheng/2018/01/18/5a600b2c99836.png@0o_0l_220w.png",
videoHeight: (screenWidth * 9) / 16.0, // 默认16:9的宽高比
videoWidth: screenWidth,
showVideoCover: true, // 是否显示视频封面
showVideoControl: false, // 是否显示视频控制组件
isPlaying: false, // 视频是否正在播放
currentTime: 0, // 视频当前播放的时间
duration: 0, // 视频的总时长
isFullScreen: false, // 当前是否全屏显示
playFromBeginning: false, // 是否从头开始播放
isShowToolBar: true,
};
控制安卓物理返回键,防止横屏退出,页面一直横屏
componentWillMount() {
if (!CommonUtils.ios) {
BackHandler.addEventListener("hardwareBackPress", this.onBackAnd);
}
}
componentWillUnmount() {
if (!CommonUtils.ios) {
BackHandler.removeEventListener("hardwareBackPress", this.onBackAnd);
}
}
onBackAnd = () => {
if (this.state.isFullScreen) {
NativeModules.DeviceOrientation.orientation("left");
this.setState({
isShowToolBar: true,
});
} else {
this.props.navigation.goBack();
}
};
Video组件回调事件
onLoadStart = () => {
console.log("视频开始加载");
};
onBuffering = () => {
console.log("视频缓冲中...");
};
onLoaded = data => {
console.log("视频加载完成");
this.setState({
duration: data.duration
});
};
onProgressChanged = data => {
console.log("视频进度更新");
if (this.state.isPlaying) {
this.setState({
currentTime: data.currentTime
});
}
};
onPlayEnd = () => {
console.log("视频播放结束");
this.setState({
currentTime: 0,
isPlaying: false,
playFromBeginning: true
});
};
onPlayError = () => {
console.log("视频播放失败");
};
控件点击事件
/// 控制播放器工具栏的显示和隐藏
hideControl() {
if (this.state.showVideoControl) {
this.setState({
showVideoControl: false
});
} else {
this.setState(
{
showVideoControl: true
},
// 5秒后自动隐藏工具栏
() => {
setTimeout(() => {
this.setState({
showVideoControl: false
});
}, 5000);
}
);
}
}
/// 点击了播放器正中间的播放按钮
onPressPlayButton() {
let isPlay = !this.state.isPlaying;
this.setState({
isPlaying: isPlay,
showVideoCover: false
});
if (this.state.playFromBeginning) {
this.videoPlayer.seek(0);
this.setState({
playFromBeginning: false
});
}
}
/// 点击了工具栏上的播放按钮
onControlPlayPress() {
this.onPressPlayButton();
}
/// 点击了工具栏上的全屏按钮
onControlShrinkPress() {
if (this.state.isFullScreen) {
// Orientation.lockToPortrait();
NativeModules.DeviceOrientation.orientation("left");
this.setState({
isShowToolBar: true,
});
} else {
// Orientation.lockToLandscape();
NativeModules.DeviceOrientation.orientation("right");
this.setState({
isShowToolBar: false,
});
}
}
/// 进度条值改变
onSliderValueChanged(currentTime) {
this.videoPlayer.seek(currentTime);
if (this.state.isPlaying) {
this.setState({
currentTime: currentTime
});
} else {
this.setState({
currentTime: currentTime,
isPlaying: true,
showVideoCover: false
});
}
}
/// 屏幕旋转时宽高会发生变化,可以在onLayout的方法中做处理,比监听屏幕旋转更加及时获取宽高变化
onLayout = event => {
//获取根View的宽高
let { width, height } = event.nativeEvent.layout;
console.log("通过onLayout得到的宽度:" + width);
console.log("通过onLayout得到的高度:" + height);
// 一般设备横屏下都是宽大于高,这里可以用这个来判断横竖屏
let isLandscape = width > height;
if (isLandscape) {
this.setState({
videoWidth: width,
videoHeight: height,
isFullScreen: true
});
} else {
this.setState({
videoWidth: width,
videoHeight: (width * 9) / 16,
isFullScreen: false
});
}
// Orientation.unlockAllOrientations();
};
/// -------外部调用事件方法-------
///播放视频,提供给外部调用
playVideo() {
this.setState({
isPlaying: true,
showVideoCover: false
});
}
/// 暂停播放,提供给外部调用
pauseVideo() {
this.setState({
isPlaying: false
});
}
/// 切换视频并可以指定视频开始播放的时间,提供给外部调用
switchVideo(videoURL, seekTime) {
this.setState({
videoUrl: videoURL,
currentTime: seekTime,
isPlaying: true,
showVideoCover: false
});
this.videoPlayer.seek(seekTime);
}
加载视频组件代码:
render() {
return (
);
}
定量以及样式
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f0f0f0"
},
playButton: {
width: 50,
height: 50
},
playControl: {
width: 24,
height: 24,
marginLeft: 15
},
shrinkControl: {
width: 15,
height: 15,
marginRight: 15
},
time: {
fontSize: 12,
color: "white",
marginLeft: 10,
marginRight: 10
},
control: {
flexDirection: "row",
height: 44,
alignItems: "center",
backgroundColor: "rgba(0, 0, 0, 0.8)",
position: "absolute",
bottom: 0,
left: 0
}
});
const screenWidth = CommonUtils.width;
function formatTime(second) {
let h = 0,
i = 0,
s = parseInt(second);
if (s > 60) {
i = parseInt(s / 60);
s = parseInt(s % 60);
}
// 补零
let zero = function(v) {
return v >> 0 < 10 ? "0" + v : v;
};
return [zero(h), zero(i), zero(s)].join(":");
}
到这里基本上是大功告成了。
对了还有最重要的一点没说,就是桥接原生,进行页面旋转。具体可以参考我的另一篇文章
react-native 实现单个页面横屏处理https://www.jianshu.com/p/09d0a54c73b2](https://www.jianshu.com/p/09d0a54c73b2