鸿蒙 模块的创建+Video简单使用

发布于:2025-05-22 ⋅ 阅读:(21) ⋅ 点赞:(0)

新建公共模块 common 导出并引入使用

  • DevEco Studio 编辑器(以下统称编辑器)左上角切到项目
  • 在项目最上层的项目名字 右键->新建->模块
  • 选择 Shared Library,取名 common,供其他模块使用,不要 static(给其他项目使用的第三方模块)
  • 在 common 模块下新建文件夹 constants 和文件 UIConstants.ets,src/main/ets/constants/UIConstants.ets
  • UIConstants 是一些静态变量,在文件 UIConstants.ets 导出它 export class UIConstants{...}
  • 在 common/Index.ets 这个文件再导出 export { UIConstants } from './src/main/ets/constants/UIConstants'
  • 假如我要在 entry 主入口模块使用 UIConstants
  • 在 entry/oh-package.json5 中引入 UIConstants,{ "dependencies": { 'common': 'file:../common' } }
  • 在 entry/pages/Index.ets 里使用 import { UIConstants } from 'common'
  • 在编辑器最上面那行里面,运行/调试配置,选择 entry->Deploy Multi Hap,勾选 Deploy Multi Hap Packages,看看 Module 里面是不是包含了 common 模块,没有就选上,不然打包会忽略 common 模块

简单使用 Video

假如是视频要联网,记得申请互联网访问权限

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET" //系统授予级权限:互联网访问,用于访问网络视频
      }
    ]
  }
}
//向其它模块共享“用户界面”相关常量
export class UIConstants {
  //颜色相关常量
  static readonly COLOR_WHITE = "#FFFFFF";
  static readonly COLOR_GRAY_LIGHTER = "#D7D7D7";
  static readonly COLOR_GRAY_LIGHT = "#AAAAAA";
  static readonly COLOR_GRAY = "#666666";
  static readonly COLOR_GRAY_DARK = "#333333";
  static readonly COLOR_GRAY_DARKER = "#1B1B1B";
  static readonly COLOR_BLACK = "#000000";
  static readonly COLOR_BLUE = "#096DD9";
  static readonly COLOR_BLUE_LIGHT = "#84B6EC";
  static readonly COLOR_BLUE_LIGHTER = "#DAE9F9";
  static readonly COLOR_RED = "#F5232E";
  static readonly COLOR_ORANGE = "#F8B865";
  static readonly COLOR_BROWN = "#AD6800";
  static readonly COLOR_YELLOW = "#FFFF00";
  //字体相关常量
  static readonly FONT_XS = 10; //Extra Small
  static readonly FONT_SM = 12; //Small
  static readonly FONT_MD = 14; //Medium
  static readonly FONT_LG = 16; //Large
  static readonly FONT_XL = 20; //Extra Large

  //间距相关常量
  static readonly SPACE_ROW_XS = 5;
  static readonly SPACE_ROW_SM = 8;
  static readonly SPACE_ROW_MD = 10;
  static readonly SPACE_ROW_LG = 13;
  static readonly SPACE_ROW_XL = 16;
  static readonly SPACE_COL_XS = 4;
  static readonly SPACE_COL_SM = 6;
  static readonly SPACE_COL_MD = 9;
  static readonly SPACE_COL_LG = 11;
  static readonly SPACE_COL_XL = 14;
  //边框相关常量
  static readonly BORDER_WIDTH_SM = 1;
  static readonly BORDER_WIDTH_MD = 2;
  static readonly BORDER_WIDTH_LG = 3;
  static readonly BORDER_RADIUS_SM = 3;
  static readonly BORDER_RADIUS_MD = 6;
  static readonly BORDER_RADIUS_LG = 9;
  //系统相关常量
  static readonly STATUS_BAR_HEIGHT = 45; //系统顶部状态栏高度
  static readonly NAVIGATION_BAR_HEIGHT = 29; //系统底部导航栏高度

  //更多...
}

代码里有些 svg 图自己去补充吧

import { window } from '@kit.ArkUI'
import { UIConstants } from 'common'


@Extend(Text)
function qsText(fs: number = UIConstants.FONT_MD, fc: string = UIConstants.COLOR_WHITE) {
  .fontSize(fs)
  .fontColor(fc)
}

@Entry
@Component
struct Index {
  @State videoSrc: Resource = $rawfile('dj.mp4') // 本地视频
  // @State videoSrc:string = 'https://www.****.com/res/0.mp4' // 云端视频
  @State posterSrc: string = ''
  @State videoTitle: string = 'Axure RP9教程:手把手教你制作视频案例'
  vc: VideoController = new VideoController()
  @Watch('watchPlaying') @State isPlaying: boolean = false //当前是否正在播放
  // @State playProgress: number = 0   //视频的播放进度,此处的0代表0%
  @State videoDuration: number = 0 //视频的总时长,单位是秒钟!不是毫秒!
  @State videoPlayedTime: number = 0 //视频已经播放的时长,单位是秒钟!不是毫秒!

  //当前页面即将显式时,设置全屏+横屏显式
  async aboutToAppear() {
    let w = await window.getLastWindow(getContext())
    w.setWindowLayoutFullScreen(true) //全屏显式
    // w.setPreferredOrientation(window.Orientation.PORTRAIT) //设置首选的屏幕方向:肖像画(竖屏)
    w.setPreferredOrientation(window.Orientation.LANDSCAPE) //设置首选的屏幕方向:风景画(横屏)
  }

  //监视isPlaying的改变
  watchPlaying() {
    if (this.isPlaying) {
      this.vc.start()
    } else {
      this.vc.pause()
    }
  }

  //把秒钟数字转化为字符串,例如: 109 => 01:49
  secondsToString(sec: number) {
    let minutes = Math.floor(sec / 60)
    let minuteString = minutes < 10 ? '0' + minutes : '' + minutes
    let seconds = sec % 60
    let secondString = seconds < 10 ? '0' + seconds : '' + seconds
    return minuteString + ':' + secondString
  }

  build() {
    RelativeContainer() {
      //F1: 视频播放组件: Video 或 XComponent
      Video({
        src: this.videoSrc, //指定视频源,可以是本地视频文件或服务器端视频文件
        previewUri: this.posterSrc, //视频尚未播放时呈现的海报/预览图
        controller: this.vc, //视频控制器
      })
        .objectFit(ImageFit.Contain)//视频尺寸包含在屏幕内(不会出现截断现象)
        .controls(false)//是否显式默认自带的播放控件
        .onPrepared((e) => {
          console.log('--视频已经就绪(已经从服务器端缓存了一定时长,可以开始播放了)', JSON.stringify(e))
          this.videoDuration = e.duration
        })
        .onUpdate((e) => {
          console.log('--播放进度更新中', JSON.stringify(e))
          this.videoPlayedTime = e.time
        })

      //F2: 顶部标题栏: Row > Image+Text
      Row() {
        Image('/images/back.svg')
          .width(11)
        Text(this.videoTitle)
          .qsText(UIConstants.FONT_XL)
          .margin({
            left: UIConstants.SPACE_ROW_XL
          })
          .layoutWeight(1) //布局权重为1,即占用父组件所有的剩余空间
        Image('/images/more.svg')
          .fillColor(UIConstants.COLOR_WHITE)
          .width(30)
      }
      .margin({
        top: UIConstants.SPACE_COL_XL
      })
      .padding({
        left: UIConstants.SPACE_ROW_XL * 2,
        right: UIConstants.SPACE_ROW_XL * 2,
      })

      //F3: 播放/暂停控制按钮
      Image(this.isPlaying ? '/images/pause2.svg' : '/images/play2.svg')
        .width(53)
        .alignRules({
          middle: { anchor: '__container__', align: HorizontalAlign.Center },
          center: { anchor: '__container__', align: VerticalAlign.Center }
        })
        .onClick(_ => {
          this.isPlaying = !this.isPlaying
        })

      //F4: 底部播放控制条
      Row() {
        Text(this.secondsToString(this.videoPlayedTime))
          .qsText()
        Row() { //使用一个父元素包裹 进度条 + 小圆饼
          Progress({
            value: this.videoPlayedTime, //进度条已播放进度就是已播放时长
            total: this.videoDuration     //进度条总长设置为视频的总时长
          })
            .color(UIConstants.COLOR_ORANGE)//已经经过的进度条颜色
            .backgroundColor(UIConstants.COLOR_WHITE) //整个进度条的背景色
          Row() {
          }
          .width(14)
          .height(14)
          .borderRadius('50%')
          .backgroundColor(UIConstants.COLOR_WHITE)
          .position({
            left: `${100 * this.videoPlayedTime / this.videoDuration}%`, //注意:此处不能直接使用字符串+拼接
            top: -5
          })
        }
        .layoutWeight(1)
        .margin({
          left: UIConstants.SPACE_ROW_MD
        })

        Text(this.secondsToString(this.videoDuration))
          .qsText()
          .margin({
            left: UIConstants.SPACE_ROW_MD
          })
        Text('高清')
          .qsText()
          .margin({
            left: UIConstants.SPACE_ROW_LG
          })
        Image('/images/zoomin.svg')
          .width(17)
          .margin({
            left: UIConstants.SPACE_ROW_XL
          })
      }
      .alignRules({
        bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
      })
      .margin({
        bottom: UIConstants.SPACE_COL_XL
      })
      .padding({
        left: UIConstants.SPACE_ROW_XL * 2,
        right: UIConstants.SPACE_ROW_XL * 2,
      })
    }
    .width('100%')
    .height('100%')
  }
}