HarmonyOS NEXT 实战视屏/全屏播放
一、介绍
基于鸿蒙Next模拟视频播放,正常播放与全屏播放
二、场景需求
大多数视频播放器都会有一个全屏按钮,通常位于视频播放窗口的右下角。点击该按钮可以进入全屏模式
三、业务步骤
第一步:准备好播放的视屏,点击左下方播放按钮,播放视频
第二部:中间可以暂停或者开始
第三步:可以拖动进度条
第三步:可以点击右下角放大icon,进行全屏播放,或者恢复正常播放
四、效果展示
五:代码展示
点击查看代码
import promptAction from '@ohos.promptAction'
import { videoSlider } from "../view/videoSlider"
@Entry
@Component
struct VideoPlayer {
@State videoSrc: string = '/common/videos/v1.mp4'
@State videoImg: string = '/common/videos/img1.png'
@State videoTitle: string = "视频标题"
@State isSupport: boolean = false
@State currentProgressRate: number = 1
@State isPlay: boolean = false; //是否播放视频
@State isAmplify: boolean = false; //是否放大
@State progressVal: number = 0; //
@State outSetValueOne: string = "0"; //视频时常
@State startTime: string = "00:00"; //开始时间
@State endTime: number = 0; //结束时间
@State endStringTime: string = "00:00"; //结束时间
@State currentTime: number = 0; //当前时间
private controller: VideoController = new VideoController(); // 视频控制器
//当前页面销毁
onPageHide() {
this.controller.pause();
}
build() {
Column() {
if (this.isAmplify){
//视频内容-全屏
Column() {
Video({
src: this.videoSrc,
previewUri: this.videoImg,
currentProgressRate:this.currentProgressRate,
controller: this.controller
})
.width("100%")
.height("92%")
.controls(false)
.autoPlay(false)
.objectFit(ImageFit.Contain)
.loop(false)
//播放时触发该事件。
.onStart(() => {})
//暂停时触发该事件。
.onPause(() => {})
//播放结束时触发该事件。
.onFinish(() => {
this.isPlay = false
})
//播放失败时触发该事件。
.onError(() => {
promptAction.showToast({message:"播放失败"})
})
//视频准备完成时触发该事件。duration:当前视频的时长,单位为秒(s)。
.onPrepared((e) => {
let d_ = e.duration
this.endTime = d_;
let min: number = Number.parseInt((d_ / 60).toString());
let second: number = d_ % 60;
let m = min < 10 ? `${'0'}${min}` : min;
let s = second < 10 ? `${'0'}${second}` : second;
this.endStringTime = `${m}${':'}${s}`;
})
//操作进度条过程时上报时间信息。time:当前视频播放的进度,单位为s。
.onSeeking((e) => {})
//操作进度条完成后,上报播放时间信息。time:当前视频播放的进度,单位为s。
.onSeeked((e) => {})
//播放进度变化时触发该事件。time:当前视频播放的进度,单位为s。
.onUpdate((e) => {
if (e) {
this.currentTime = e.time;
let second: number = this.currentTime % 60;
let min: number = Number.parseInt((this.currentTime / 60).toString());
let start_m = min < 10 ? `${'0'}${min}` : min;
let start_s = second < 10 ? `${'0'}${second}` : second;
this.startTime = `${start_m}${':'}${start_s}`;
}
})
//在全屏播放与非全屏播放状态之间切换时触发该事件。fullscreen:返回值为true表示进入全屏播放状态,为false则表示非全屏播放
.onFullscreenChange(() => {})
Blank()
videoSlider({
startTime:$startTime,
endTime:$endTime,
endStringTime:$endStringTime,
currentTime: $currentTime,
isPlay:$isPlay,
isAmplify:$isAmplify,
isSupport:$isSupport,
controller: this.controller,
})
Blank()
}.width("100%")
.height("100%")
.backgroundColor(0x999999)
}else {
//视屏内容
Column() {
Video({
src: this.videoSrc,
previewUri: this.videoImg,
currentProgressRate:this.currentProgressRate,
controller: this.controller
})
.height(383)
.controls(false)
.autoPlay(false)
.objectFit(ImageFit.Contain)
.loop(false)
//播放时触发该事件。
.onStart(() => {})
//暂停时触发该事件。
.onPause(() => {})
//播放结束时触发该事件。
.onFinish(() => {
this.isPlay = false
})
//播放失败时触发该事件。
.onError(() => {
promptAction.showToast({message:"播放失败"})
})
//视频准备完成时触发该事件。duration:当前视频的时长,单位为秒(s)。
.onPrepared((e) => {
let d_ = e.duration
this.endTime = d_;
let min: number = Number.parseInt((d_ / 60).toString());
let second: number = d_ % 60;
let m = min < 10 ? `${'0'}${min}` : min;
let s = second < 10 ? `${'0'}${second}` : second;
this.endStringTime = `${m}${':'}${s}`;
})
//操作进度条过程时上报时间信息。time:当前视频播放的进度,单位为s。
.onSeeking((e) => { })
//操作进度条完成后,上报播放时间信息。time:当前视频播放的进度,单位为s。
.onSeeked((e) => {})
//播放进度变化时触发该事件。time:当前视频播放的进度,单位为s。
.onUpdate((e) => {
if (e) {
this.currentTime = e.time;
let second: number = this.currentTime % 60;
let min: number = Number.parseInt((this.currentTime / 60).toString());
let start_m = min < 10 ? `${'0'}${min}` : min;
let start_s = second < 10 ? `${'0'}${second}` : second;
this.startTime = `${start_m}${':'}${start_s}`;
}
})
//在全屏播放与非全屏播放状态之间切换时触发该事件。fullscreen:返回值为true表示进入全屏播放状态,为false则表示非全屏播放
.onFullscreenChange(() => {})
//进度条
videoSlider({
startTime:$startTime,
endTime:$endTime,
endStringTime:$endStringTime,
currentTime: $currentTime,
isPlay:$isPlay,
isAmplify:$isAmplify,
isSupport:$isSupport,
controller: this.controller,
})
}.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
.width('100%')
.height('100%')
}
}
点击查看代码
videoSlider.ets
@Component
export struct videoSlider {
@Link startTime: string //开始时间
@Link endTime: number //视频时常
@Link endStringTime: string //视频时常
@Link currentTime: number //当前时间
@Link isPlay: boolean //播放键
@Link isAmplify: boolean //放大
@Link isSupport: boolean //点赞
private controller: VideoController = new VideoController();
//转换时间
transformTime(n:number){
let min = Math.floor(n / 60); // 计算分钟
let sec = n % 60; // 计算剩余秒数
let m = min < 10 ? "0" + min : min;
let s = sec < 10 ? "0" + sec : sec;
return m + ":" + s
}
build(){
Row() {
// 播放暂停按钮-是否播放
Image(this.isPlay ? $r('app.media.ic_pause') : $r('app.media.ic_play'))
.height(24)
.margin({ left: 4,right:4 })
.onClick(() => {
this.isPlay = !this.isPlay
if (this.isPlay === true) {
this.controller.start()
}else {
this.controller.pause()
}
})
Text(this.startTime).fontSize(12) // 视频初始时间
Slider({
value: this.currentTime,
min: 0,
max: this.endTime,
style: SliderStyle.OutSet
})
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
this.currentTime = value
this.controller.setCurrentTime(value, SeekMode.Accurate);
this.startTime = this.transformTime(value)
console.info('value:' + value + 'mode:' + mode.toString())
})
.width("44%")
Text(this.endStringTime).fontSize(12) // 视频总时长
Image(this.isAmplify ? $r('app.media.ic_celiakeyboard_magnify') : $r('app.media.ic_gallery_full_screen'))
.width(24)
.height(24)
.margin({ left: 8,right:8 })
.onClick(() => {
this.isAmplify = !this.isAmplify
})
Image(this.isSupport ? $r('app.media.ic_public_thumbsup_filled') : $r('app.media.ic_public_thumbsup'))
.width(24)
.height(24)
.margin({ left: 8,right:8 })
.onClick(() => {
this.isSupport = !this.isSupport
})
}
.width('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(0x999999)
}
}