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

Posted HarmonyOS技术社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenHarmony标准设备应用开发——布局动画与音乐相关的知识,希望对你有一定的参考价值。

上一章我们讲解了应用编译环境准备,设备编译环境准备,开发板烧录,将一个最简单的 OpenAtom OpenHarmony(以下简称“OpenHarmony”)程序安装到我们的标准设备上。


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


分布式音乐播放


通过分布式音乐播放器,大家可以学到一些 ArkUI 组件和布局在 OpenHarmony 中是如何使用的,以及如何在自己的应用中实现音乐的播放,暂停等相关功能。应用效果如下图所示:OpenHarmony标准设备应用开发(二)——布局、动画与音乐_UI

1.1界面布局

整体布局效果如下图所示

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

代码参考链接 :

​https://gitee.com/openharmony-sig/knowledge_demo_temp/blob/master/FA/Entertainment/DistrubutedMusicPlayer/entry/src/main/ets/MainAbility/pages/index.ets​


首先是页面整体布局,部分控件是以模块的方式放在整体布局中的,如 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 开发的面向多种全场景智能设备的商用版本。是结合其自有特性和能力开发的新一代智能终端操作系统。

官网参考链接:

​https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-basic-components.md​


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/blob/master/FA/Entertainment/DistrubutedMusicPlayer/entry/src/main/ets/Common/PlayerManager.ets​


分布式音乐播放器项目下载链接:

​https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/Entertainment/DistrubutedMusicPlayer​

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



显示动画


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

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

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

代码链接:

​https://gitee.com/openharmony-sig/knowledge_demo_temp/blob/master/FA/Entertainment/BombGame/entry/src/main/ets/MainAbility/pages/game.ets​


实现步骤:

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 中的使用,如何模块化的使用布局,让自己的代码更简洁易读,以及在应用中实现页面间的转场动画效果。

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

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

代码参考链接:

​https://gitee.com/openharmony-sig/knowledge_demo_temp/blob/master/FA/Shopping/DistributedShoppingCart/entry/src/main/ets/MainAbility/pages/HomePage.ets​


页面布局效果图

整体布局由 Column、Scroll、Flex、Image 以及 GoodsHome()、MyInfo()、HomeBottom() 构成,该三个模块我们会分别说明。具体代码如下:OpenHarmony标准设备应用开发(二)——布局、动画与音乐_UI_05

整体布局由 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)


项目下载链接地址:

​https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/Shopping/DistributedShoppingCart​


官网参考链接:

​https://gitee.com/openharmony/docs/blob/OpenHarmony-3.1-Beta/zh-cn/application-dev/reference/arkui-ts/ts-page-transition-animation.md​


通过上述讲解,我们就在自己的代码中实现音乐的播放,显示动画,页面间转场动画等效果。在接下来的一章中,我们会讲解如何在 OpenHarmony 通过分布式数据管理,实现设备之间数据如何同步刷新。

 在接下来的一章中,我们将会讲解分布式数据管理在 OpenHarmony 中如何实现多台设备间的数据同步更新。

​想了解更多关于鸿蒙的内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://harmonyos.51cto.com/#bkwz​


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




以上是关于OpenHarmony标准设备应用开发——布局动画与音乐的主要内容,如果未能解决你的问题,请参考以下文章

富设备标准平台:基于RK3568的DAYU200进入OpenHarmony 3.1 Relea

OpenHarmony内核学习[1]--单独编译OpenHarmony标准系统内核

精品课程OpenHarmony L0设备开发入门——支持Pegasus智能家居开发套件

OpenHarmony-标准设备系统代码操作梳理

#DAYU200体验官# OpenHarmony标准系统运行docker软件

#DAYU200体验官# OpenHarmony3.2的编译烧录