OpenHarmony标准设备应用开发(二)——布局、动画与音乐
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点)
邢碌
上一章我们讲解了应用编译环境准备,设备编译环境准备,开发板烧录,将一个最简单的 OpenAtom OpenHarmony(以下简称“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().url
this.player.on('dataLoad', () => {
CommonLog.info('dataLoad duration=' + this.player.duration)
this.totalTimeMs = this.player.duration
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.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
}
分布式音乐播放器项目下载链接:https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/Entertainment/DistrubutedMusicPlayer
接下来我们讲解如何在 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 = null build() {
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)
}
项目下载链接:https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/Entertainment/BombGame
三、转场动画(页面间转场)
我们同样希望在本小节中,可以让大家看到更多的 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 条目所构成。具体代码如下:
@Component
struct GoodsHome {
private goodsItems: GoodsData[]
@Consume ShoppingCartsGoods :any[]
build() {
Column() {
Tabs() {
TabContent() {
GoodsList({ goodsItems: this.goodsItems});
}
.tabBar("畅销榜")
.backgroundColor(Color.White) TabContent() {
GoodsList({ goodsItems: this.goodsItems});
}
.tabBar("推荐")
.backgroundColor(Color.White)
}
.barWidth(500)
.barHeight(50)
.scrollable(true)
.barMode(BarMode.Scrollable)
.height('980lpx') }
.alignItems(HorizontalAlign.Start)
.width('100%')
}
}
上面代码中的 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标准设备应用开发(二)——布局、动画与音乐的更多相关文章
- OpenHarmony标准设备应用开发(三)——分布式数据管理
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 邢碌 上一章,我们通过分布式音乐播放器.分布式炸弹.分布式购物车,带大家讲解了 OpenAtom OpenHarmon ...
- OpenHarmony标准设备应用开发(一)——HelloWorld
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 邢碌 本文是 OpenAtom OpenHarmony(以下简称"OpenHarmony")标准设 ...
- Android动画效果之自定义ViewGroup添加布局动画
前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...
- IOS开发系列 --- 核心动画
原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- 动画_ _ Android应用开发之所有动画使用详解
转载: http://blog.csdn.net/yanbober/article/details/46481171 题外话:有段时间没有更新博客了,这篇文章也是之前写了一半一直放在草稿箱,今天抽空把 ...
- (Java)微信之个人公众账号开发(二)——接收并处理用户消息(下)
接下来,我们再讲一下图文消息: 如图: 大家可以先从开发者文档中了解一下图文消息的一些参数: 如上图,用户回复4时,ipastor返回了几条图文消息,上图中属于多图文消息,当然还有单图文消息,图文消息 ...
- 自定义ViewGroup添加布局动画
声明几个属性值: <declare-styleable name="GridImageViewGroup"> <attr name="childVert ...
- android 属性动画和布局动画p165-p171
一.属性动画 ObjectAnimator ObjectAnimator是属性动画框架中最重要的实行类,创建一个ObjectAnimator只需通过他的静态工厂类直接返回一个ObjectAnimato ...
- Android应用开发之所有动画使用详解
题外话:有段时间没有更新博客了,这篇文章也是之前写了一半一直放在草稿箱,今天抽空把剩余的补上的.消失的这段时间真的好忙,节奏一下子有些适应不过来,早晨七点四十就得醒来,晚上九点四十才准备下班,好像最近 ...
随机推荐
- [bzoj3585] Rmq Problem / mex
[bzoj3585] Rmq Problem / mex bzoj luogu 看上一篇博客吧,看完了这个也顺理成章会了( (没错这篇博客就是这么水) #include<cstdio> # ...
- P2P图书馆实践:让知识更好的传播
人才是每个公司最重要的资产,而人的成长自然就成了最重要的事.苏轼曾经说过:"腹有诗书气自华,代码万行零缺陷",阅读对人成长的影响是巨大的.相信不同的团队都有着自己打造学习氛围.技术 ...
- 如何在 Mac 上强制退出 App
同时按住三个按键:Option.Command 和 Esc (Escape) 键.或者,从屏幕左上角的苹果菜单 中选取"强制退出".(这类似于在 PC 上按下 Control- ...
- Kafka创建Topic时如何将分区放置到不同的Broker中?
副本因子不能大于 Broker 的个数: 第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的: 其他分区的第一个副本放置位置相对于第0个分区依次往后移.也就是如果我们有5 ...
- 使用SpringDataJdbc无法注册的情况
当 EnableJdbcRepositories 注解无法注册Repository仓库的时候,你可以查看下 你的实体是否存在@Table注解,没有请加上,这样就能扫描到了 @Table("b ...
- MyISAM 表格将在哪里存储,并且还提供其存储格式?
每个 MyISAM 表格以三种格式存储在磁盘上: ·".frm"文件存储表定义 ·数据文件具有".MYD"(MYData)扩展名 索引文件具有".MY ...
- MySQL 里记录货币用什么字段类型?
NUMERIC 和 DECIMAL 类型被 MySQL 实现为同样的类型,这在 SQL92 标准允 许.他们被用于保存值,该值的准确精度是极其重要的值,例如与金钱有关的数 据.当声明一个类是这些类型之 ...
- 转:C++初始化成员列表
转载至:https://blog.csdn.net/zlintokyo/article/details/6524185 C++初始化成员列表和新机制初始化表达式列表有几种用法: 1.如果类存在继承关系 ...
- ArrayList跟LinkedList的区别
ArrayList和LinkedList都是实现list接口,它们不同如下: ArrayList是基于索引的数据接口,底层是数组.它可以以O(1)时间复杂度对元素进行随机访问.与此相对,linkedL ...
- ACM - 动态规划 - UVA437 The Tower of Babylon
UVA437 The Tower of Babylon 题解 初始时给了 \(n\) 种长方体方块,每种有无限个,对于每一个方块,我们可以选择一面作为底.然后用这些方块尽可能高地堆叠成一个塔,要求只有 ...