第19篇:视频课程模块——列表、播放与版权保护

img

一、引言

视频课程是驾考应用的重要组成部分,为用户提供驾驶技巧的直观教学。DriverLicenseExam 项目实现了视频列表展示、视频详情播放、会员专属内容等完整功能。本文将深入解析视频课程模块的实现。

二、视频数据结构

2.1 Video 接口

// commons/datasource/src/main/ets/Model.ets
export interface Video {
  poster: Resource;         // 视频封面图
  url: string;              // 视频地址
  name: string;             // 视频名称
  simpleDescription: string; // 简短描述
  description: string;      // 详细描述
  copyrightNotice: string;  // 版权声明
  time: string;             // 时长
  needVip?: boolean;        // 是否需要会员
}

2.2 视频数据生成

// ExamService.getVideList
public getVideList(): Video[] {
  const videoUrl: string = ExamService.context.resourceManager
    .getStringSync($r('app.string.video_url').id);
  
  return [
    {
      poster: $r('app.media.video_poster'),
      url: videoUrl,
      name: '倒车入库',
      simpleDescription: '两步掌握倒车入库',
      description: '侧方位停车有两个地方需要注意:...',
      copyrightNotice: '未经许可,请勿转载使用',
      time: '01:04',
    },
    {
      poster: $r('app.media.video_poster'),
      url: videoUrl,
      name: '侧方位停车',
      simpleDescription: '三步掌握侧方位停车',
      description: '...',
      copyrightNotice: '未经许可,请勿转载使用',
      time: '01:04',
      needVip: true,  // 会员专属
    },
  ];
}

三、视频列表展示

3.1 水平滚动列表

// HomeView.ets 中的视频列表
Column({ space: 12 }) {
  Text('考场必考项目讲解')
    .fontSize(16)
    .fontColor($r('sys.color.font_primary'));

  List({ space: 12 }) {
    ForEach(this.videoList, (item: Video) => {
      ListItem() {
        Column({ space: 8 }) {
          RelativeContainer() {
            Image(item.poster)
              .width(CommonConstants.FULL_WIDTH)
              .height(CommonConstants.FULL_HEIGHT);

            Image($r('app.media.play_button'))
              .width(24).height(24)
              .alignRules({
                bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
                right: { anchor: '__container__', align: HorizontalAlign.End }
              })
              .offset({ x: -8, y: -8 });
          }
          .height(80)
          .onClick(() => {
            this.vm.navStack.pushPathByName('videoDetailView', item);
          });

          Text(item.name)
            .fontSize(14)
            .fontColor($r('sys.color.font_secondary'))
            .maxFontScale(1);
        }
        .width(104);
      }
    });
  }
  .listDirection(Axis.Horizontal)
  .scrollBar(BarState.Off);
}

四、视频详情播放

4.1 视频详情页

// VideoDetailView.ets
@ComponentV2
export struct VideoDetailView {
  @Local video: Video = this.vm.navStack.getParamByIndex(
    this.vm.navStack.size() - 1) as Video;

  build() {
    NavDestination() {
      Scroll() {
        Column() {
          // 视频播放器
          Video({
            src: this.video.url,
            controller: this.videoController
          })
          .width('100%')
          .height(200);

          // 视频信息
          Text(this.video.name).fontSize(20).fontWeight(FontWeight.Bold);
          Text(this.video.description).fontSize(14);
          Text(this.video.copyrightNotice).fontSize(12).fontColor('#999');
        }
        .padding(16);
      }
    }
    .title(this.video.name);
  }
}

五、会员专属内容控制

5.1 会员判断

// 判断用户是否有权限观看
get canWatch(): boolean {
  if (!this.video.needVip) return true;  // 非会员内容,所有用户可看
  return AccountUtil.getAccountInfo().idToken !== '';  // 会员内容需登录
}

5.2 会员提示

// 非会员用户点击会员视频时提示
if (this.video.needVip && !this.isLoggedIn) {
  showToast('开通会员后可观看', this.getUIContext());
  return;
}

六、总结

视频课程模块实现了完整的视频展示和播放功能,包括:

  1. 视频列表:水平滚动列表展示视频封面
  2. 视频详情:播放器 + 视频信息展示
  3. 会员控制:needVip 字段控制会员专属内容
  4. 版权保护:版权声明信息展示

关键源码文件:

  • commons/datasource/src/main/ets/ExamService.ets — 视频数据
  • commons/datasource/src/main/ets/Model.ets — Video 接口
  • products/entry/src/main/ets/pages/home/HomeView.ets — 视频列表
  • products/entry/src/main/ets/pages/video/VideoDetailView.ets — 视频详情
  • products/entry/src/main/ets/pages/video/VideoListView.ets — 视频列表页
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐