OpenHarmony标准设备应用开发(二)——布局、动画与音乐

本章是 OpenHarmony 标准设备应用开发的第二篇文章。我们通过知识体系新开发的几个基于 OpenHarmony3.1 Beta 标准系统的样例:分布式音乐播放、传炸弹、购物车等样例,分别介绍下音乐播放、显示动画、动画转场(页面间转场)三个进阶技能。首先我们来讲如何在 OpenHarmony 中实现音乐的播放。

一、分布式音乐播放

通过分布式音乐播放器,大家可以学到一些 ArkUI 组件和布局在 OpenHarmony 中是如何使用的,以及如何在自己的应用中实现音乐的播放,暂停等相关功能。应用效果如下图所示:

1.1 界面布局

整体布局效果如下图所示:

首先是页面整体布局,部分控件是以模块的方式放在整体布局中的,如 operationPannel()、sliderPannel()、playPannel() 模块。页面整体布是由 Flex 控件中,包含 Image、Text 以及刚才所说的三个模块所构成。

build() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End }) {Image($r("app.media.icon_liuzhuan")).width(32).height(32)}.padding({ right: 32 }).onClick(() => {this.onDistributeDevice()})Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center }) {Image($r("app.media.Bg_classic")).width(312).height(312)}.margin({ top: 24 })Text(this.currentMusic.name).fontSize(20).fontColor("#e6000000").margin({ top: 10 })Text("未知音乐家").fontSize(14).fontColor("#99000000").margin({ top: 10 })}.flexGrow(1)Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.End }) {this.operationPannel()this.sliderPannel()this.playPannel()}.height(200)}.linearGradient({angle: 0,direction: GradientDirection.Bottom,colors: this.currentMusic.backgourdColor}).padding({ top: 48, bottom: 24, left: 24, right: 24 }).width('100%').height('100%')}

operationPannel() 模块的布局,该部分代码对应图片中的心形图标,下载图标,评论图标更多图标这一部分布局。其主要是在 Flex 中包含 Image 所构成代码如下:

@Builder operationPannel() {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {Image($r("app.media.icon_music_like")).width(24).height(24)Image($r("app.media.icon_music_download")).width(24).height(24)Image($r("app.media.icon_music_comment")).width(24).height(24)Image($r("app.media.icon_music_more")).width(24).height(24)}.width('100%').height(49).padding({ bottom: 25 })}

sliderPannel() 模块代码布局。该部分对应图片中的显示播放时间那一栏的控件。整体构成是在 Flex 中,包含 Text、Slider、Text 三个控件。具体代码如下:

@Builder sliderPannel() {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Text(this.currentTimeText).fontSize(12).fontColor("ff000000").width(40)Slider({value: this.currentProgress,min: 0,max: 100,step: 1,style: SliderStyle.INSET}).blockColor(Color.White).trackColor(Color.Gray).selectedColor(Color.Blue).showSteps(true).flexGrow(1).margin({ left: 5, right: 5 }).onChange((value: number, mode: SliderChangeMode) => {if (mode == 2) {CommonLog.info('aaaaaaaaaaaaaa1: ' + this.currentProgress)this.onChangeMusicProgress(value, mode)}})Text(this.totalTimeText).fontSize(12).fontColor("ff000000").width(40)}.width('100%').height(18)}

playPannel() 模块代码对应图片中的最底部播放那一栏五个图标所包含的一栏。整体布局是 Flex 方向为横向,其中包含五个 Image 所构成。具体代码如下:

@Builder playPannel() {Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {Image($r("app.media.icon_music_changemode")).width(24).height(24).onClick(() => {this.onChangePlayMode()})Image($r("app.media.icon_music_left")).width(32).height(32).onClick(() => {this.onPreviousMusic()})Image(this.isPlaying ? $r("app.media.icon_music_play") : $r("app.media.icon_music_stop")).width(80).height(82).onClick(() => {this.onPlayOrPauseMusic()})Image($r("app.media.icon_music_right")).width(32).height(32).onClick(() => {this.onNextMusic()})Image($r("app.media.icon_music_list")).width(24).height(24).onClick(() => {this.onShowMusicList()})}.width('100%').height(82)}

希望通过上面这些布局的演示,可以让大家学到一些部分控件在 OpenHarmony 中的运用,这里使用的 Arkui 布局和 HarmonyOS* 是一致的,目前 HarmonyOS* 手机还没有发布 Arkui 的版本,大家可以在 OpenHarmony 上抢先体验。常用的布局和控件还有很多,大家可以在下面的链接中找到更多的详细信息。

*编者注:HarmonyOS 是基于开放原子开源基金会旗下开源项目 OpenHarmony 开发的面向多种全场景智能设备的商用版本。是结合其自有特性和能力开发的新一代智能终端操作系统。

1.2 播放音乐

play(seekTo) {if (this.player.state == 'playing' && this.player.src == this.getCurrentMusic().url) {return}if (this.player.state == 'idle' || this.player.src != this.getCurrentMusic().url) {CommonLog.info('Preload music url = ' + this.getCurrentMusic().url)this.player.reset()this.player.src = this.getCurrentMusic().urlthis.player.on('dataLoad', () => {CommonLog.info('dataLoad duration=' + this.player.duration)this.totalTimeMs = this.player.durationif (seekTo > this.player.duration) {seekTo = -1}this.player.on('play', (err, action) => {if (err) {CommonLog.info(`MusicPlayer[PlayerModel] error returned in play() callback`)return}if (seekTo > 0) {this.player.seek(seekTo)}})this.player.play()this.statusChangeListener()this.setProgressTimer()this.isPlaying = true})}else {if (seekTo > this.player.duration) {seekTo = -1}this.player.on('play', (err, action) => {if (err) {CommonLog.info(`MusicPlayer[PlayerModel] error returned in play() callback`)return}if (seekTo > 0) {this.player.seek(seekTo)}})this.player.play()this.setProgressTimer()this.isPlaying = true}}

1.3 音乐暂停

pause() {CommonLog.info("pause music")this.player.pause();this.cancelProgressTimer()this.isPlaying = false}

接下来我们讲解如何在 OpenHarmony 中实现显示动画的效果。

二、显示动画

我们以传炸弹小游戏中的显示动画效果为例,效果如下图所示。

通过本小节,大家在上一小节的基础上,学到更多 ArkUI 组件和布局在 OpenHarmony 中的应用,以及如何在自己的应用中实现显示动画的效果。

实现步骤:

**2.1 编写弹窗布局:**将游戏失败文本、炸弹图片和再来一局按钮图片放置于 Column 容器中;

**2.2 用变量来控制动画起始和结束的位置:**用 Flex 容器包裹炸弹图片,并用 @State 装饰变量 toggle,通过变量来动态修改 Flex 的 direction 属性;布局代码如下:

@State toggle: boolean = true
private controller: CustomDialogController
@Consume deviceList: RemoteDevice[]
private confirm: () => void
private interval = nullbuild() {Column() {Text('游戏失败').fontSize(30).margin(20)Flex({direction: this.toggle ? FlexDirection.Column : FlexDirection.ColumnReverse,alignItems: ItemAlign.Center}){Image($r("app.media.bomb")).objectFit(ImageFit.Contain).height(80)}.height(200)Image($r("app.media.btn_restart")).objectFit(ImageFit.Contain).height(120).margin(10).onClick(() => {this.controller.close()this.confirm()})}.width('80%').margin(50).backgroundColor(Color.White)
}

**2.3 设置动画效果:**使用 animateTo 显式动画接口炸弹位置切换时添加动画,并且设置定时器定时执行动画,动画代码如下:

aboutToAppear() {this.setBombAnimate()
}setBombAnimate() {let fun = () => {this.toggle = !this.toggle;}this.interval = setInterval(() => {animateTo({ duration: 1500, curve: Curve.Sharp }, fun)}, 1600)
}

三、转场动画(页面间转场)

我们同样希望在本小节中,可以让大家看到更多的 ArkUI 中的组件和布局在 OpenHarmony 中的使用,如何模块化的使用布局,让自己的代码更简洁易读,以及在应用中实现页面间的转场动画效果。

下图是分布式购物车项目中的转场动画效果图:

页面布局效果图:

整体布局由 Column、Scroll、Flex、Image 以及 GoodsHome()、MyInfo()、HomeBottom() 构成,该三个模块我们会分别说明。具体代码如下:

build() {Column() {Scroll() {Column() {if (this.currentPage == 1) {Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End }) {Image($r("app.media.icon_share")).objectFit(ImageFit.Cover).height('60lpx').width('60lpx')}.width("100%").margin({ top: '20lpx', right: '50lpx' }).onClick(() => {this.playerDialog.open()})GoodsHome({ goodsItems: this.goodsItems})}else if (this.currentPage == 3) {//我的MyInfo()}}.height('85%')}.flexGrow(1)HomeBottom({ remoteData: this.remoteData})}.backgroundColor("white")}

GoodsHome() 模块对应效果图中间显示商品的部分,其主要结构为 TabContent 中包含的两个 List 条目所构成。具体代码如下:

build() {Column() {Scroll() {Column() {if (this.currentPage == 1) {Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End }) {Image($r("app.media.icon_share")).objectFit(ImageFit.Cover).height('60lpx').width('60lpx')}.width("100%").margin({ top: '20lpx', right: '50lpx' }).onClick(() => {this.playerDialog.open()})GoodsHome({ goodsItems: this.goodsItems})}else if (this.currentPage == 3) {//我的MyInfo()}}.height('85%')}.flexGrow(1)HomeBottom({ remoteData: this.remoteData})}.backgroundColor("white")}

上面代码中的 GoodsList() 为每个 list 条目对应显示的信息,会便利集合中的数据,然后显示在对用的 item 布局中,具体代码如下:

@Component
struct GoodsList {private goodsItems: GoodsData[]@Consume ShoppingCartsGoods :any[]build() {Column() {List() {ForEach(this.goodsItems, item => {ListItem() {GoodsListItem({ goodsItem: item})}}, item => item.id.toString())}.width('100%').align(Alignment.Top).margin({ top: '10lpx' })}}
}

最后就是 list 的 item 布局代码。具体代码如下:

@Component
struct GoodsListItem {private goodsItem: GoodsData@State scale: number = 1@State opacity: number = 1@State active: boolean = false@Consume ShoppingCartsGoods :any[]build() {Column() {Navigator({ target: 'pages/DetailPage' }) {Row({ space: '40lpx' }) {Column() {Text(this.goodsItem.title).fontSize('28lpx')Text(this.goodsItem.content).fontSize('20lpx')Text('¥' + this.goodsItem.price).fontSize('28lpx').fontColor(Color.Red)}.height('160lpx').width('50%').margin({ left: '20lpx' }).alignItems(HorizontalAlign.Start)Image(this.goodsItem.imgSrc).objectFit(ImageFit.ScaleDown).height('160lpx').width('40%').renderMode(ImageRenderMode.Original).margin({ right: '20lpx', left: '20lpx' })}.height('180lpx').alignItems(VerticalAlign.Center).backgroundColor(Color.White)}.params({ goodsItem: this.goodsItem ,ShoppingCartsGoods:this.ShoppingCartsGoods}).margin({ left: '40lpx' })}}

**备注:**MyInfo() 模块对应的事其它也免得布局,这里就不做说明。

最后我们来说一下,页面间的页面间的转场动画,其主要是通过在全局 pageTransition 方法内配置页面入场组件和页面退场组件来自定义页面转场动效。具体代码如下:

// 转场动画使用系统提供的多种默认效果(平移、缩放、透明度等)pageTransition() {PageTransitionEnter({ duration: 1000 }).slide(SlideEffect.Left)PageTransitionExit({ duration: 1000  }).slide(SlideEffect.Right)}
}

为了帮助到大家能够更有效的学习OpenHarmony 开发的内容,下面特别准备了一些相关的参考学习资料:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/12740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI工具的热门与卓越:揭示AI技术的实际应用和影响

文章目录 每日一句正能量前言常用AI工具创新AI应用个人体验分享后记 每日一句正能量 我们在我们的劳动过程中学习思考,劳动的结果,我们认识了世界的奥妙,于是我们就真正来改变生活了。 前言 随着人工智能(AI)技术的快…

深度剖析MyBatis的二级缓存

二级缓存的原理 MyBatis 二级缓存的原理是什么? 二级缓存的原理和一级缓存一样,第一次查询会将数据放到 缓存 中,然后第二次查询直接去缓存读取。但是一级缓存是基于 SqlSession 的,二级缓存是基于 mapper 的 namespace 的。也就是…

关于API接口的自述

在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台API接口,或者提供API接口给第三方平台调用。 那么问题来了,如果设计一个优雅的API接口,能够满足:安全性、可重复调用、稳定性、好定位问…

Qt运行时,如何设置第一个聚焦的控件

问题:Qt第一个聚焦的控件,如何自行设置? 尝试: 1.在代码中设置 lineEdit->setFocus() 。无效! 2.Qt Designer–打开form1.ui–菜单栏下一行–Edit Tab Order–按顺序点击–菜单栏下一行–Edit Widgets–退出。无效…

为什么做了功能测试还要做接口测试

接口测试与功能测试不是重复的测试,而是互为补充的测试策略。 在软件测试领域,接口测试和功能测试被视为质量保证过程中至关重要的组成部分。尽管它们之间存在部分重复,但更多的情况下,它们相辅相成,各自发挥着独特的作用。本文将探讨接口测试与功能测试之间的关系,以及它…

【easyX】动手轻松掌握easyX 1

01 简单绘图 在这个程序中&#xff0c;我们先初始化绘图窗口。其次&#xff0c;简单绘制两条线。 #include <graphics.h>//绘图库头文件 #include <stdio.h> int main() {initgraph(640, 480);//初始化640✖480绘图屏幕line(200, 240, 440, 240);//画线(200,240)…

MySQL是如何选择索引的?

2.3.5. 索引选择 MySQL是如何选择索引的&#xff1f; 优化器决定了具体某一索引的选择&#xff0c;也就是常说的执行计划。而优化器的选择是基于成本&#xff08;cost&#xff09;&#xff0c;哪个索引的成本越低&#xff0c;优先使用哪个索引。 SQL 优化器会分析所有可能的执…

Python操作鼠标键盘和爬虫

一.pyautogui 库 pyautogui 是一个 Python 库&#xff0c;允许控制鼠标和键盘。可以通过它编写 Python 脚本来自动执行各种任务&#xff0c;例如点击按钮、输入文本、移动鼠标等。这个库非常适合用来编写自动化脚本来完成重复性的工作&#xff0c;比如网页表单填写、屏幕截图、…

STC8增强型单片机开发——定时器Timer

一、定时器 定时器是一种计时装置&#xff0c;通常由一个晶体振荡器提供时钟信号&#xff0c;可以计时一定的时间后执行相应的操作。在单片机中&#xff0c;定时器一般是由计数器和时钟源组成的&#xff0c;可以用来产生一定时间间隔的中断信号&#xff0c;或者用于测量输入信号…

开放式运动耳机哪款好用?五款高性能值得信赖产品推荐

身为户外运动的达人&#xff0c;我发现开放式运动耳机简直是咱们运动时的最佳拍档&#xff0c;不管是跑步还是健身&#xff0c;开放式运动耳机最为舒适&#xff0c;它的妙处就在于不用塞进耳朵&#xff0c;这样既安全又卫生&#xff0c;户外动起来更放心。但市面上好坏参半&…

AIGC行业:探索发展风口,把握市场脉搏

AIGC行业现在适合进入吗 简介&#xff1a; AIGC行业&#xff1a;探索发展风口&#xff0c;把握市场脉搏 随着人工智能技术的快速发展&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;行业正逐渐成为科技界的新宠。在当前的时代背景下&#xff0c;我们不禁要问&…

Chisel中对对<: 和:的理解(其实是Scala中的理解)

在 Scala 语言和 Chisel 硬件构造语言中&#xff0c;<: 和 : 是用于类型注解的两个不同的符号&#xff0c;它们在泛型编程和类型系统中扮演重要角色。下面是它们各自的意义和用途&#xff1a; <:&#xff08;子类型关系&#xff09; <: 符号在 Scala 中表示子类型关…

Nginx详细介绍一

Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;它也可以作为邮件服务器使用。 Nginx基本介绍 基本概念&#xff1a; Nginx可以处理大量的并发连接&#xff0c;具有很高的稳定性和低资源消耗的特点。它主要用于Web服务、反向代理、负载均衡和HTTP缓存等场景。 安装与配…

【半夜学习MySQL】内置函数(含日期、字符串、数学等函数常用用法介绍及示例详解)

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 日期函数字符串函数数学函数其他函数 日期函数 函数名称描述current_date()当前日期current_time()当前时间current_time()…

php8.2使用laravel V11.0

报错&#xff1a;You must enable the openssl extension in your php.ini to load information from https://mirrors.aliyun.com/composer 1、搜索&#xff1a;extension_dir去掉;号 2、搜索&#xff1a;extensionopenssl去掉;号

幻兽帕鲁Palworld服务器手动部署

目录 帕鲁官方文档手动安装steamcmd通过steamcmd安装帕鲁后端客户端连接附录&#xff1a;PalServer.sh的启动项附录&#xff1a;配置文件 帕鲁官方文档 https://tech.palworldgame.com/ 手动安装steamcmd 创建steam用户 sudo useradd -m steam sudo passwd steam下载steamc…

你写HTML的时候,会注重语义化吗?

其实说到语义化&#xff0c;多年前端开发经验的老手估计也不会太在意&#xff0c;有时候工期太紧&#xff0c;有时候自己疏忽&#xff0c;也就不那么在意了&#xff0c;直接DIVCSS一把梭下去了。 目录 什么是HTML 什么是HTML语义化 HTML语义化所带来的好处 我把CSS样式引入…

_pickle.UnpicklingError: STACK_GLOBAL requires str

导致这个报错的原因是我跑yolo的时候修改数据集了&#xff0c;里面的label.cache没有删除&#xff0c;咱只要删除掉缓存就行&#xff01;&#xff01; 我这里是已经删除掉了&#xff0c;所以图片里面没有&#xff0c;一般就是在箭头所示位置有.cache文件的

Vue3知识总结-4

Vue3知识总结-4 文章目录 Vue3知识总结-4插槽Slots渲染作用域默认内容具名插槽插槽中的数据传递具名插槽传递数据 组件声明周期声明周期示意图 组件生命周期的应用动态组件组件保持存活组件被卸载 异步组件依赖注入 插槽Slots 在某些场景中&#xff0c;可能想要为子组件传递一…

xxljob分片广播+多线程实现高效定时同步elasticsearch索引库

需求&#xff1a;为了利用elasticsearch实现高效搜索&#xff0c;需要将mysql中的数据查出来&#xff0c;再定时同步到es里&#xff0c;同时在同步过程中通过分片广播多线程提高同步数据的效率。 1. 添加映射 使用kibana添加映射 PUT /app_info_article {"mappings&quo…