<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

HarmonyOS開發案例:【視頻播放器】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-23 17:25 ? 次閱讀

介紹

使用ArkTS語言實現視頻播放器,主要包括主界面和視頻播放界面,我們將一起完成以下功能:

  1. 主界面頂部使用Swiper組件實現視頻海報輪播。
  2. 主界面下方使用List組件實現視頻列表。
  3. 播放界面使用Video組件實現視頻播放。
  4. 在不使用視頻組件默認控制器的前提下,實現自定義控制器。
  5. 播放界面底部使用圖標控制視頻播放/暫停。
  6. 播放界面底部使用Slider組件控制和實現視頻播放進度。
  7. 播放界面使用Stack容器組件的[Z序控制]實現在視頻播放畫面上添加開始/暫停/加載圖標。

相關概念

  • [Swiper]組件:滑動容器,提供切換子組件顯示的能力。
  • [List]組件:列表包含一系列相同寬度的列表項。適合連續、多行呈現同類數據,例如圖片和文本。
  • [Video]組件:用于播放視頻文件并控制其播放狀態的組件。
  • [Navigator]組件:路由容器組件,提供路由跳轉能力。
  • [ForEach]組件:基于數組類型數據執行循環渲染。
  • 鴻蒙開發指導文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

環境搭建

軟件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 開發板類型:[潤和RK3568開發板]。
  • OpenHarmony系統:3.2 Release。

環境搭建

完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:

  1. [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)。以3.2 Release版本為例:
  2. 搭建燒錄環境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發板的燒錄]
  3. 搭建開發環境。
    1. 開始前請參考[工具準備],完成DevEco Studio的安裝和開發環境配置。
    2. 開發環境配置完成后,請參考[使用工程向導]創建工程(模板選擇“Empty Ability”)。
    3. 工程創建完成后,選擇使用[真機進行調測]。
    4. HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿

搜狗高速瀏覽器截圖20240326151344.png

代碼結構解讀

本篇Codelab只對核心代碼進行講解,對于完整代碼,我們會在gitee中提供。

├──entry/src/main/ets             // 代碼區
│  ├──common
│  │  └──constants
│  │     └──CommonConstants.ets   // 樣式常量類
│  ├──entryability
│  │  └──EntryAbility.ts          // 程序入口類
│  ├──model
│  │  └──VideoControll.ets        // 視頻播放控制相關方法類
│  ├──pages
│  │  ├──SimpleVideoIndex.ets     // 主界面
│  │  └──SimpleVideoPlay.ets      // 視頻播放界面
│  ├──view
│  │  ├──IndexModule.ets          // 自定義首頁List模塊組件文件
│  │  ├──IndexSwiper.ets          // 自定義首頁Swiper組件文件
│  │  ├──VideoPlayer.ets          // 自定義播放界面視頻組件文件
│  │  └──VideoPlaySlider.ets      // 自定義播放界面視頻進度條組件文件
│  └──viewmodel
│     ├──HorizontalVideoItem.ets  // 水平視頻類
│     ├──ParamItem.ets            // 參數
│     ├──SwiperVideoItem.ets      // 自定義播放界面視頻組件文件
│     └──VideoData.ets            // 首頁相關數據
└──entry/src/main/resource        // 應用靜態資源目錄

構建主界面

主界面由視頻輪播模塊和多個視頻列表模塊組成,效果如圖所示:

VideoData.ets中定義的視頻輪播圖數組SWIPER_VIDEOS和視頻列表圖片數組HORIZONTAL_VIDEOS。

// VideoData.ets
import { HorizontalVideoItem } from './HorizontalVideoItem';
import { SwiperVideoItem } from './SwiperVideoItem';

export const SWIPER_VIDEOS: SwiperVideoItem[] = [
  new SwiperVideoItem($r('app.media.ic_banner1')),
  new SwiperVideoItem($r('app.media.ic_banner2')),
  new SwiperVideoItem($r('app.media.ic_banner3'))
];

export const HORIZONTAL_VIDEOS: HorizontalVideoItem[] = [
  new HorizontalVideoItem(1, $r('app.media.ic_video_list0'), '視頻1'),
  new HorizontalVideoItem(2, $r('app.media.ic_video_list1'), '視頻2'),
  new HorizontalVideoItem(3, $r('app.media.ic_video_list2'), '視頻3')
];

IndexSwiper.ets文件中定義的輪播圖子組件SwiperVideo,點擊輪播圖片,頁面跳轉到視頻播放頁面,并攜帶本地視頻flag,效果如圖所示:

// IndexSwiper.ets
@Component
export struct SwiperVideo {
  build() {
    Column() {
      Swiper() {
        ForEach(SWIPER_VIDEOS, (item: SwiperVideoItem) = > {
          SwiperItem({ imageSrc: item.image, source: $rawfile('videoTest.mp4') })
        }, (item: SwiperVideoItem) = > JSON.stringify(item))
      }
      .autoPlay(true)
    }
    // 樣式設置
    ...
  }
}

@Component
struct SwiperItem {
  private imageSrc: Resource = $r('app.string.empty');
  private source: Resource = $r('app.string.empty');
  private paramItem: ParamItem = new ParamItem();
  ...
  build() {
    // 跳轉一:使用Navigator組件跳轉到視頻播放界面
    Navigator({ target: SECOND_PAGE, type: NavigationType.Push }) {
      Image(this.imageSrc)
        .borderRadius(MARGIN_FONT_SIZE.FIRST_MARGIN)
    }
    .params(this.paramItem)
  }
}

IndexModule.ets文件中定義的視頻列表圖片子組件VideoModule,點擊子組件中的圖片,頁面跳轉到視頻播放頁面,并攜帶網絡視頻flag,效果如圖所示:

// IndexModule.ets
@Component
export struct VideoModule {
  private moduleName: string = '';

  build() {
    Column() {
      // 視頻列表上方的文本信息
      ...
      // 視頻列表組件
      List({ space: MARGIN_FONT_SIZE.FIRST_MARGIN }) {
        ForEach(HORIZONTAL_VIDEOS, (item: HorizontalVideoItem) = > {
          ListItem() {
            HorizontalItem({
              imageSrc: item.image,
              source: NET,
              videoName: item.name
            })
          }
        }, (item: HorizontalVideoItem) = > JSON.stringify(item))
      }
      // 設置列表橫向排列
      .listDirection(Axis.Horizontal)
    }
    // 樣式設置
    ...
  }
}

@Component
struct HorizontalItem {
  private imageSrc: Resource = $r('app.string.empty');
  private source: string = '';
  private videoName: string = '';

  build() {
    // 跳轉二:使用route跳轉到視頻播放界面
    Column() {
      Image(this.imageSrc)
        .width(MARGIN_FONT_SIZE.SEVENTH_MARGIN)
        .height(MARGIN_FONT_SIZE.SIXTH_MARGIN)
        .onClick(() = > {
          router.pushUrl({
            url: SECOND_PAGE,
            params: { source: this.source }
          });
        })
     ...
    }
    .justifyContent(FlexAlign.Center)
  }
}

在SimpleVideoIndex.ets主界面中引用SwiperVideo和VideoModule子組件。

// SimpleVideoIndex.ets
@Entry
@Component
struct SimpleVideoIndex {
  build() {
    Column({ space: MARGIN_FONT_SIZE.FOURTH_MARGIN }) {
      // 視頻輪播組件
      SwiperVideo()
      List() {
        ForEach(LIST, (item: string) = > {
          ListItem() {
            VideoModule({ moduleName: item })
              .margin({ top: MARGIN_FONT_SIZE.FIRST_MARGIN })
          }
        }, (item: string) = > JSON.stringify(item))
      }
      .listDirection(Axis.Vertical)
      .margin({ top: MARGIN_FONT_SIZE.THIRD_MARGIN })
    }
    ...
  }
}

構建視頻播放界面

VideoPlayer.ets其中定義了視頻播放子組件VideoPlayer ,onPrepared回調方法中可以獲取視頻總時長,onUpdate回調方法中可實時獲取到視頻播放的當前時間戳,onFinish是視頻播放結束后的回調方法,onError是視頻播放出錯的回調方法。

// VideoPlayer.ets
@Component
export struct VideoPlayer {
  private source: string | Resource = '';
  private controller: VideoController = new VideoController();
  private previewUris: Resource = $r('app.media.preview');
  @Provide currentTime: number = 0;
  @Provide durationTime: number = 0;
  @Provide durationStringTime: string = START_TIME;
  @Provide currentStringTime: string = START_TIME;
  @Consume isPlay: boolean;
  @Consume isOpacity: boolean;
  @Consume flag: boolean;
  @Consume isLoading: boolean;
  @Consume progressVal: number;

  build() {
    Column() {
      Video({
        src: this.source,
        previewUri: this.previewUris,
        controller: this.controller
      })
        .width(ALL_PERCENT)
        .height(STRING_PERCENT.NINETY_PERCENT)
        .controls(false)
        .autoPlay(false)
        .objectFit(ImageFit.Contain)
        .loop(false)
        .onUpdate((event) = > {
          if (event) {
            this.currentTime = event.time;
            this.currentStringTime = changeSliderTime(this.currentTime);
          }
        })
        .onPrepared((event) = > {
          this.prepared(event?.duration);
        })
        .onFinish(() = > {
          this.finish();
        })
        .onError(() = > {
          prompt.showToast({
            duration: COMMON_NUM_DURATION,
            message: MESSAGE
          });
        })
      VideoSlider({ controller: this.controller })
    }
  }
  ...
}

在自定義組件VideoPlayer底部使用了自定義子組件VideoSlider,VideoSlider自定義組件中顯示和控制視頻播放進度,效果如圖所示:

// VideoPlaySlider.ets
@Component
export struct VideoSlider {
  @Consume isOpacity: boolean;
  private controller: VideoController = new VideoController();
  @Consume currentStringTime: string;
  @Consume currentTime: number;
  @Consume durationTime: number;
  @Consume durationStringTime: string;
  @Consume isPlay: boolean;
  @Consume flag: boolean;
  @Consume isLoading: boolean;
  @Consume progressVal: number;

  build() {
    Row({ space: MARGIN_FONT_SIZE.FIRST_MARGIN }) {
      ...
      Slider({
        value: this.currentTime,
        min: 0,
        max: this.durationTime,
        step: 1,
        style: SliderStyle.OutSet
      })
        .blockColor($r('app.color.white'))
        .width(STRING_PERCENT.SLIDER_WITH)
        .trackColor(Color.Gray)
        .selectedColor($r("app.color.white"))
        .showSteps(true)
        .showTips(true)
        .trackThickness(this.isOpacity ? SMALL_TRACK_THICK_NESS : BIG_TRACK_THICK_NESS)
        .onChange((value: number, mode: SliderChangeMode) = > {
          this.sliderOnchange(value, mode);
        })
      ...
    }
    .opacity(this.isOpacity ? DEFAULT_OPACITY : 1)
    ...
  }
  ...
}

在VideoController.ets中的視頻控制和回調的相關方法。

// VideoControll.ets
export function changeSliderTime(value: number): string {
  let second: number = value % COMMON_NUM_MINUTE;
  let min: number = Number.parseInt((value / COMMON_NUM_MINUTE).toString());
  let head = min < COMMON_NUM_DOUBLE ? `${ZERO_STR}${min}` : min;
  let end = second < COMMON_NUM_DOUBLE ? `${ZERO_STR}${second}` : second;
  let nowTime = `${head}${SPLIT}${end}`;
  return nowTime;
}

在SimpleVideoPlay.ets播放界面,引用VideoPlayer子組件,并在視頻播放頁面使用堆疊容器,在視頻播放畫面中心堆疊控制、視頻加載圖標,效果如圖所示:

// SimpleVideoPlay.ets
@Entry
@Component
struct Play {
  // 取到Index頁面跳轉來時攜帶的source對應的數據。
  private source: string = (router.getParams() as Record< string, Object >).source as string;
  private startIconResource: Resource = $r('app.media.ic_public_play');
  private backIconResource: Resource = $r('app.media.ic_back');
  @Provide isPlay: boolean = false;
  @Provide isOpacity: boolean = false;
  controller: VideoController = new VideoController();
  @Provide isLoading: boolean = false;
  @Provide progressVal: number = 0;
  @Provide flag: boolean = false;

  ...
  onPageHide() {
    this.controller.pause();
  }

  build() {
    Column() {
      // 頂部返回以及標題
...
      Stack() {
        // 不同的播放狀態渲染不同得控制圖片
        if (!this.isPlay && !this.isLoading) {
          Image(this.startIconResource)
            .width(MARGIN_FONT_SIZE.FIFTH_MARGIN)
            .height(MARGIN_FONT_SIZE.FIFTH_MARGIN)
            // 同一容器中兄弟組件顯示層級關系,z值越大,顯示層級越高 用于控制圖片在視頻上。
            .zIndex(STACK_STYLE.IMAGE_Z_INDEX)
        }
        if (this.isLoading) {
          Progress({
            value: STACK_STYLE.PROGRESS_VALUE,
            total: STACK_STYLE.PROGRESS_TOTAL,
            type: ProgressType.ScaleRing
          })
            .color(Color.Grey)
            .value(this.progressVal)
            .width(STACK_STYLE.PROGRESS_WIDTH)
            .style({
              strokeWidth: STACK_STYLE.PROGRESS_STROKE_WIDTH,
              scaleCount: STACK_STYLE.PROGRESS_SCALE_COUNT,
              scaleWidth: STACK_STYLE.PROGRESS_SCALE_WIDTH
            })
            .zIndex(STACK_STYLE.PROGRESS_Z_INDEX)
        }
        VideoPlayer({
          source: this.source,
          controller: this.controller
        })
          .zIndex(0)
      }
    }
    .height(ALL_PERCENT)
    .backgroundColor(Color.Black)
  }
}

sf

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 視頻播放器
    +關注

    關注

    0

    文章

    33

    瀏覽量

    11799
  • 鴻蒙
    +關注

    關注

    55

    文章

    1966

    瀏覽量

    42222
  • HarmonyOS
    +關注

    關注

    79

    文章

    1910

    瀏覽量

    29498
  • OpenHarmony
    +關注

    關注

    24

    文章

    3443

    瀏覽量

    15332
收藏 人收藏

    評論

    相關推薦

    3568F-視頻開發案

    3568F-視頻開發案
    的頭像 發表于 04-12 13:51 ?604次閱讀
    3568F-<b class='flag-5'>視頻</b><b class='flag-5'>開發案</b>例

    鴻蒙開發-視頻播放器方案

    HarmonyOS系統中,提供兩種視頻播放開發的方案: [AVPlayer]:功能較完善的音視頻播放ArkTS/JS API,集成了流媒體
    發表于 02-19 17:20

    靈活電影播放器視頻/音頻播放軟件

    東京,2008年4月24日--瑞薩科技公司(Renesas Techno logy Corp.)今天宣布,推出為采用移動電話SH-Mobile*1應用處理的嵌入式系統開發的靈活電影播放器
    發表于 03-06 19:52

    【OK210申請】手持視頻播放器

    申請理由:父親節的時候,給老爸買了一個先科視頻播放器,能讀優盤和SD卡,但是沒用多長時間就壞掉了,因為自己也比較愛好硬件和軟件開發,所以萌生自己做一個的想法,如果有了這款開發版我只要做
    發表于 07-17 17:06

    HarmonyOS應用開發-視頻播放

    HarmonyOS應用開發E2E體驗,學到了:如何創建一個HarmonyOS Demo Project如何構建一個Hap并且將其部署到真機在HarmonyOS上如何使用
    發表于 09-11 17:25

    HarmonyOS IoT 硬件開發案例分享

    ``許思維老師HiSpark Wi-Fi IoT 開發案例分享:案例一:AHT20溫濕度傳感開發、調試;案例二:oled屏驅動庫移植,調試;案例三:用OLED屏播放
    發表于 10-27 17:30

    基于HarmonyOS Player,實現視頻文件的播放

    會學到什么如何使用Player類播放視頻如何使用自定義控件來控制視頻播放如何添加并使用媒體事件的事件偵聽和回調2. 搭建
    發表于 09-18 13:51

    DistributedVideoPlayer分布式視頻播放器的設計資料

    1、DistributedVideoPlayer分布式視頻播放器的設計資料(一)本示例是在官方Video Play Ability 模板基礎上做了擴展開發,官方模板提供基本的視頻
    發表于 03-22 11:55

    基于HarmonyOS ets開發的簡易視頻播放器

    這是我們使用HarmonyOS的codelab簡易視頻播放器的codelab簡易播放器。內容就是一個主視頻界面,包括頂部的
    發表于 04-18 10:41

    網頁視頻播放器代碼

    網頁視頻播放器代碼
    發表于 01-10 11:23 ?102次下載
    網頁<b class='flag-5'>視頻</b><b class='flag-5'>播放器</b>代碼

    關于VR電影視頻播放器 盤點12款VR播放器

    VR電影和視頻那個播放器好,哪些播放器更為實用,由于視頻資源格式多樣,在一個播放器播放不了的
    發表于 06-27 15:50 ?12.3w次閱讀

    數碼播放器開發案

    數碼播放器開發案例說明。
    發表于 05-19 11:07 ?6次下載

    HarmonyOS開發案例:【視頻播放器

    基于video、swiper和slider組件,實現簡單的視頻播放器,可支持海報輪播、視頻播放等功能。
    的頭像 發表于 04-22 21:06 ?146次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發案</b>例:【<b class='flag-5'>視頻</b><b class='flag-5'>播放器</b>】

    HarmonyOS開發案例:【音樂播放器

    使用ArkTS語言實現了一個簡易的音樂播放器應用
    的頭像 發表于 04-23 15:44 ?373次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發案</b>例:【音樂<b class='flag-5'>播放器</b>】

    HarmonyOS開發案例:【視頻播放器

    使用ArkTS語言實現視頻播放器,主要包括主頁面和視頻播放頁面
    的頭像 發表于 04-24 14:52 ?307次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發案</b>例:【<b class='flag-5'>視頻</b><b class='flag-5'>播放器</b>】
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>