鸿蒙4.0实战教学—基础ArkTS(简易视频播放器)
构建主界面
主界面由视频轮播模块和多个视频列表模块组成,效果图如图:
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.banner1')),new SwiperVideoItem($r('app.media.banner2')),new SwiperVideoItem($r('app.media.banner3'))
];export const HORIZONTAL_VIDEOS: HorizontalVideoItem[] = [new HorizontalVideoItem(1, $r('app.media.video_list0'), '视频1'),new HorizontalVideoItem(2, $r('app.media.video_list1'), '视频2'),new HorizontalVideoItem(3, $r('app.media.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)}
}
本文主要是对鸿蒙开发中基础ArkTS语言的运用实操,更多的鸿蒙开发实操技术学习,可以前往主页学习更多的鸿蒙核心技术。下面是分享一份鸿蒙开发技术学习路线(略缩图)
高清完整版保存主页找我
最后
使用ArkTS语言实现视频播放器,主要包括主界面和视频播放界面,效果图如下:
相关文章:

鸿蒙4.0实战教学—基础ArkTS(简易视频播放器)
构建主界面 主界面由视频轮播模块和多个视频列表模块组成,效果图如图: VideoData.ets中定义的视频轮播图数组SWIPER_VIDEOS和视频列表图片数组HORIZONTAL_VIDEOS。 // VideoData.ets import { HorizontalVideoItem } from ./HorizontalVideoItem; impo…...
4. 深入 Python 流程控制
4. 深入 Python 流程控制 除了前面介绍的 while 语句,Python 还从其它语言借鉴了一些流程控制功能,并有所改变。 4.1. if 语句 也许最有名的是 if 语句。例如: >>> x int(raw_input("Please enter an integer: "))…...

2000-2022年上市公司股票流动性指标数据/股票流动性Amihud(原始数据+计算代码+计算结果)
2000-2022年上市公司股票流动性指标数据/股票流动性Amihud(原始数据计算代码计算结果) 1、时间:2000-2022年 3、指标:证券代码_没有单位、交易日期_没有单位、日个股交易金额_元、考虑现金红利再投资的日个股回报率_没有单位、交…...
Unity 数据存储PlayerPrefs管理类
Unity 数据存储PlayerPrefs管理类 Unity 数据存储PlayerPrefs管理类实现存取实体类对象存储格式为Json格式Singleton.csInventoryEntity.csDataManager.cs用法如下 Unity 数据存储PlayerPrefs管理类 实现存取实体类对象 存储格式为Json格式 源码如下: Singleton…...
一篇文章学会如何使用 NestJS 过滤器处理系统全局异常情况
前言 在实际的应用开发中,你或许遇到过异常处理机制不统一或错误信息展示混乱的现象。为了解决这些问题,NestJS提供了一个优雅的解决方案:过滤器(Filter)。本文将从实际出发,向你介绍NestJS过滤器的基本概…...
ubuntu 守护进程 supervisor
# 安装 apt-get install supervisor# 检查 echo_supervisord_conf# 查看配置文件所在位置 # [include] # files /etc/supervisor/conf.d/*.conf ps -ef | grep supervisorcd /etc/supervisor/conf.d/lscat frp.conf[program:frp] command /data/work/frp/frpc -c /data/work/…...

SparkStreaming_window_sparksql_reids
1.5 window 滚动窗口滑动窗口 window操作就是窗口函数。Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作。每次掉落在窗口内的RDD的数据,会被聚合起来执行计算操作,然后生成的RDD,会…...
爬虫工作量由小到大的思维转变---<第二十四章 Scrapy的`统计数据`收集stats collection ---12月26日补>
前言: 前两篇是讲的数据诊断分析,还有一篇深挖解决内存泄漏的文章,目前我还没整理汇编出来;但是,想到分析问题的时候,忽然觉得爬虫的数据统计好像也挺重要;于是,心血来潮准备来插一篇这个------让大家对日常scrapy爬的数据,做到心里有数!不必自己去搅破脑汁捣腾日志,敲计算器了…...

Kafka:本地设置
这是设置 Kafka 将数据从 Elasticsearch 发布到 Kafka 主题的三部分系列的第一部分;该主题将被 Neo4j 使用。第一部分帮助您在本地设置 Kafka。第二部分将讨论如何设置Elasticsearch将数据发布到Kafka主题。最后 将详细介绍如何使用连接器订阅主题并使用数据。 Kafka Kafka 是…...

.NetCore NPOI 读取excel内容及单元格内图片
由于数据方提供的数据在excel文件中不止有文字内容还包含图片信息,于是编写相关测试代码,读取excel文件内容及图片信息. 本文使用的是 NPOI-2.6.2 版本,此版本持.Net4.7.2;.NetStandard2.0;.NetStandard2.1;.Net6.0。 测试文档内容…...
TCP/UDP协议
1. 请解释TCP和UDP的主要区别。 TCP和UDP都是位于传输层的协议,具有不同的特点和应用场景。以下是它们的主要区别: 连接方式:TCP是面向连接的协议,这意味着在数据传输之前需要先建立连接。这通常通过三次握手来建立连接ÿ…...

3D 渲染如何帮助电商促进销售?
在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 3D 渲染图像因其高转化率而成为亚马逊卖家的最新趋势。它是电子商务平…...
使用栈求表达式的值【数据结构】
中缀表达式转后缀表达式 转换流程: 初始化一个运算符栈。自左向右扫描中缀表达式,当扫描到操作数时直接连接到后缀表达式上。当扫描到操作符时,和运算符栈栈顶的操作符进行比较。如果比栈顶运算符高,则入栈。如果比栈顶运算符低…...

{MySQL}索引事务和JDBC
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、索引1.1索引是什么1.2作用1.3代码 二、事务2.1什么是事务2.2使用 三.JDBC总结 前言 接着上次,继续讲下MySQL 提示:以下是本篇文章正…...

Qt designer界面和所有组件功能的详细介绍(全!!!)
PyQt5和Qt designer的详细安装教程:https://blog.csdn.net/qq_43811536/article/details/135185233?spm1001.2014.3001.5501 目录 1. 界面介绍2. Widget Box 常用组件2.1 Layouts(布局)2.2 Spacers(间隔器)2.3 Item V…...
mysql_存储过程
举例子 createdefiner root% procedure insert_batch_test(IN START int(10), IN max_num int(10)) BEGINDECLAREi INT DEFAULT 0;SET autocommit 0;REPEATSET i i 1;INSERT INTO test (std, score)VALUES (CEILING(RAND() * 10 100), CEILING(RAND() * 50 50));UNTIL i …...
uboot学习及内核更换_incomplete
官方文档 在前面 文章目录 uboot常见命令学习环境变量网络控制台uboot标准启动其他 升级uboot或内核bin和uimg以及booti和bootm的区别制作uImage更换内核更换uboot后续计划 uboot常见命令学习 环境变量 Environment Variables环境变量 autostart 如果值为yes,则会…...

KVM 自动化脚本的使用及热/冷迁移
一、介绍 目录结构介绍 [rootkvm-server kvm]# tree -L 2 . ├── control # 控制脚本目录 │ ├── KVMInstall.sh # kvm服务安装脚本 │ ├── VMHost.sh # kvm虚拟机克隆脚本 │ └── VMTemplate.sh # kvm模板机安装脚本 ├── mount # 此目录保持为空&…...

Unity中Shader裁剪空间推导(在Shader中使用)
文章目录 前言一、在Shader中使用转化矩阵1、在顶点着色器中定义转化矩阵2、用 UNITY_NEAR_CLIP_VALUE 区分平台矩阵3、定义一个枚举用于区分当前是处于什么相机 二、我们在DirectX平台下,看看效果1、正交相机下2、透视相机下3、最终代码 前言 在上一篇文章中&…...

ES的使用(Elasticsearch)
ES的使用(Elasticsearch) es是什么? es是非关系型数据库,是分布式文档数据库,本质上是一个JSON 文本 为什么要用es? 搜索速度快,近乎是实时的存储、检索数据 怎么使用es? 1.下载es的包(环境要…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...

【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...