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)
  }
}

posted @ 2024-09-27 11:59  李洋蛟龙腾飞  阅读(29)  评论(0编辑  收藏  举报