最近工作业务用到了react-native-video,还需要能够全屏,全屏需要用到锁定应用方向(横屏),需要用到组件react-native-orientation-locker,本文记录使用方法以及提供一种解决思路。
横竖屏方法
我就只介绍这常用的三个,其他的可以翻看官方文档
import Orientation from 'react-native-orientation-locker';
Orientation.lockToLandscapeLeft() // 向左方向锁定横屏
Orientation.lockToLandscapeRight() // 向右方向锁定横屏
Orientation.unlockAllOrientations(); // 解除锁定
Orientation.lockToPortrait(); // 锁定竖屏
导入
import Video from 'react-native-video';
函数部分
// 设置总时长
setDuration({ duration }) {
this.setState({ duration });
}
// 播放结束可将暂停变量设置为true
onEnd() {
this.setState({
paused: true,
});
}
// 缓冲,loading变量可控制缓冲圈显示
onBuffer({ isBuffering }) {
this.setState({ loading: isBuffering });
}
// 设置进度条和播放时间的变化,sliderValue用来同步步进器
setTime({ currentTime }) {
this.setState({
sliderValue: currentTime,
});
}
// 播放暂停
changePlayed() {
this.setState({ paused: !this.state.paused });
}
视频组件
<View style={styles.Video}>
{
loading ? <View style={styles.loading}>
<ActivityIndicator size='large' color='lightgray' /> // 缓冲圈
</View> : null
}
<Video
ref={(ref: Video) => {
this.video = ref; // 视频Video的ref
}}
source={{
uri: 'http://xxx/xxx.mp4', //播放路径
}}
style={{ width: '100%', height: '100%' }}
rete={1}
volume={1}
paused={paused} // 暂停变量
onEnd={() => {
this.onEnd(); // 播放结束时执行
}}
onBuffer={data => this.onBuffer(data)} // 缓冲时执行,用于显示缓冲圈
onProgress={data => this.setTime(data)} // 播放时执行函数,用于同步步进器进度
onLoad={data => this.setDuration(data)} // 播放前得到总时长,用于步进器设置总长
muted={muted} // 静音
/>
</View>
控制台
<View style={styles.videoControl}>
{/* 暂停按钮 */}
<TouchableOpacity
onPress={() => {
this.changePlayed();
}}
>
<Image style={styles.paused} source={paused ? pausedImg : played} />
</TouchableOpacity>
<Slider
value={sliderValue}
maximumValue={duration}
// onValueChange 和 onSlidingComplete 是修改步进器进度时触发的函数
// 可以在此时同步视频播放,同步视频播放的函数是,video的Ref.seek()
// 中间需要设置视频暂停和播放,否则边拖动边播放会很奇怪
onValueChange={(value) => {
this.video.seek(value);
this.setState({
paused: true,
});
}}
onSlidingComplete={(value) => {
this.video.seek(value);
this.setState({
paused: false,
});
}}
style={styles.slider}
/>
{/* 静音按钮 */}
<TouchableOpacity
onPress={() => {
this.setState({ muted: !muted });
}}
>
<Image style={{ marginLeft: 10, height: 24, width: 24 }} source={muted ? mute : sound} />
</TouchableOpacity>
{/* 全屏按钮 */}
<TouchableOpacity
onPress={() => {
// 这里涉及到react-native-orientation-locker
// 可以锁定应用为横屏,这里的状态设置是我的全屏解决方案
this.setState({ fullVideoShow: true, sliderValue2: sliderValue }, () => {
this.setState({ paused: true });// 需要将原视频暂停
});
Orientation.lockToLandscapeLeft();
}}
>
<Image style={{ marginLeft: 10, height: 20, width: 20 }} source={fullScreen} />
</TouchableOpacity>
</View>
我采用的是弹出层方案,使用Orientation横屏时,新建一个model层覆盖全屏,然后新建一个相同的播放组件,记得将原视频组件暂停。
可以参考的点,以下表示model层上的视频组件
// 放大时,总长已经不需要再次获取,我们可以在onLoad2时将sliderValue赋值给video2
// 达到放大时同步进度的效果
onLoad2(data) {
this.video2.seek(this.state.sliderValue);
}
// 设置vedio2的同步步进器2进度时,需要注意,currentTime>0再赋值
// 否则在视频加载过程中会出现步进器2跳一下0再恢复的情况
setTime2({ currentTime }) {
if (currentTime > 0) {
this.setState({
sliderValue2: currentTime,
});
}
}
// 退出全屏
outFullScreen() {
const { sliderValue2, paused2 } = this.state;
this.setState({ fullVideoShow: false, sliderValue: sliderValue2);
Orientation.lockToPortrait();
// 退出时将原视频进度同步
this.video.seek(sliderValue2);
}
// 播放暂停
changePlayed2() {
this.setState({ paused2: !this.state.paused2 });
}
// 另外全屏时,要将原视频paused暂停,可以在全屏按钮事件那里我有提到。
放大视频
<Modal
visible={fullVideoShow}
transparent
animationType='slide'
>
<View style={styles.videoModelBack}>
<View style={styles.videoModel}>
{
loading ? <View style={styles.loading}>
<ActivityIndicator size='large' color='lightgray' /> //缓冲圈可复用状态
</View> : null
}
<View style={{ flex: 1 }}>
<Video
ref={(ref: Video) => {
this.video2 = ref;
}}
source={{
uri: 'http://xxx/xxx.mp4',
}}
style={{ flex: 1 }}
rete={1}
volume={1}
paused={paused2}
onEnd={() => {
this.onEnd(0);
}}
onBuffer={data => this.onBuffer(data)}
onProgress={data => this.setTime2(data)}
onLoad={data => this.onLoad2(data)}
muted={muted}
/>
</View>
</View>
<View style={styles.videoBack}>
<TouchableOpacity
onPress={() => {
this.changePlayed2();
}}
>
<Image style={[styles.paused]} source={paused2 ? pausedImg : played} />
</TouchableOpacity>
<Slider
value={sliderValue2}
maximumValue={duration}
onValueChange={(value) => {
this.video2.seek(value);
this.setState({
paused2: true,
});
}}
onSlidingComplete={(value) => {
this.video2.seek(value);
this.setState({
paused2: false,
});
}}
style={styles.slider}
/>
<TouchableOpacity
onPress={() => {
this.setState({ muted: !muted });
}}
>
<Image style={styles.img} source={muted ? mute : sound} />
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.outFullScreen();
}}
>
<Image source={outFullScreen} /> // 退出全屏按钮
</TouchableOpacity>
</View>
</View>
</Modal>
样式我没有写出来,因为内容可能比较多,布局情况也不大相同,想完全复用不太现实,不过如果你耐心点理解重要的部分,相信你会有所收获。
如果觉得文章对你有帮助的话,欢迎点赞收藏哦,有什么错误或者意见建议也可以留言,感谢~