鸿蒙OS开发:【一次开发,多端部署】(音乐专辑主页)

一多音乐专辑主页

介绍

本示例展示了音乐专辑主页。

  • 头部返回栏: 因元素单一、位置固定在顶部,因此适合采用自适应拉伸,充分利用顶部区域。
  • 专辑封面: 使用栅格组件控制占比,在小尺寸屏幕下封面图与歌单描述在同一行。
  • 歌曲列表: 使用栅格组件控制宽度,在小尺寸屏幕下宽度为屏幕的100%,中尺寸屏幕下宽度为屏幕的50%,大尺寸屏幕下宽度为屏幕的75%。
  • 播放器: 采用自适应拉伸,充分使用底部区域。

本示例使用一次开发多端部署中介绍的自适应布局能力和响应式布局能力进行多设备(或多窗口尺寸)适配,保证应用在不同设备或不同窗口尺寸下可以正常显示。

用到了媒体查询接口[@ohos.mediaquery]。

效果预览

本示例在预览器中的效果:

本示例在开发板上运行的效果:

image.png

使用说明:

1.启动应用,查看本应用在全屏状态下的效果。

2.在应用顶部,下滑出现窗口操作按钮。(建议通过外接鼠标操作,接入鼠标只需要将鼠标移动至顶部即可出现窗口)

3.点击悬浮图标,将应用悬浮在其他界面上显示。

4.拖动应用悬浮窗口的四个顶角,改变窗口尺寸,触发应用显示刷新。改变窗口尺寸的过程中,窗口尺寸可能超出屏幕尺寸,此时在屏幕中只能看到应用部分区域的显示。可以通过移动窗口位置,查看应用其它区域的显示。

开发前请熟悉鸿蒙开发指导文档gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。

工程目录

AppMarket/entry/src/main/ets/
|---model
|   |---MediaData.ets                      // 主页用到的图片资源
|   |---SongList.ets                       // 歌曲数据
|   |---SongModule.ets                     // 事件监听函数模块
|---pages                                  
|   |---index.ets                          // 首页
|---common                                    
|   |---Content.ets                        // 内容组件
|   |---Header.ets                         // 标题栏
|   |---Player.ets                         // app模块(包含安装,展示图片,更多功能)
|   |---PlayList.ets                       // 歌单列表
|   |---PlayListCover.ets                  // 歌单封面                                          

具体实现

本示例介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口,将页面分拆为4个部分。

标题栏

由于在不同断点下,标题栏始终只显示“返回按钮”、“歌单”以及“更多按钮”,但“歌单”与“更多按钮”之间的间距不同。
通过栅格实现:将标题栏划分为“返回按钮及歌单”和“更多按钮”两部分,这两部分在不同断点下占据的列数不同。

歌单封面

通过栅格实现歌单封面,它由封面图片、歌单介绍及常用操作三部分组成这三部分的布局在md和lg断点下完全相同,但在sm断点下有较大差异,[源码参考]。

/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { optionList } from '../model/SongList'@Componentexport default struct PlayListCover {@State imgHeight: number = 0@StorageProp('coverMargin') coverMargin: number = 0@StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm'@StorageProp('fontSize') fontSize: number = 0@BuilderCoverImage() {Stack({ alignContent: Alignment.BottomStart }) {Image($r('app.media.pic_album')).width('100%').aspectRatio(1).borderRadius(8).onAreaChange((oldArea: Area, newArea: Area) => {this.imgHeight = newArea.height as number})Text($r('app.string.collection_num')).letterSpacing(1).fontColor('#fff').fontSize(this.fontSize - 4).translate({ x: 10, y: '-100%' })}.width('100%').height('100%').aspectRatio(1)}@BuilderCoverIntroduction() {Column() {Text($r('app.string.list_name')).opacity(0.9).fontWeight(500).fontColor('#556B89').fontSize(this.fontSize + 2).margin({ bottom: 10 })Text($r('app.string.playlist_Introduction')).opacity(0.6).width('100%').fontWeight(400).fontColor('#556B89').fontSize(this.fontSize - 2)}.width('100%').height(this.currentBreakpoint === 'sm' ? this.imgHeight : 70).alignItems(HorizontalAlign.Start).justifyContent(FlexAlign.Center).padding({ left: this.currentBreakpoint === 'sm' ? 20 : 0 }).margin({top: this.currentBreakpoint === 'sm' ? 0 : 30,bottom: this.currentBreakpoint === 'sm' ? 0 : 20})}@BuilderCoverOptions() {Row() {ForEach(optionList, item => {Column({ space: 4 }) {Image(item.image).height(30).width(30)Text(item.text).fontColor('#556B89').fontSize(this.fontSize - 1)}})}.width('100%').height(70).padding({left: this.currentBreakpoint === 'sm' ? 20 : 0,right: this.currentBreakpoint === 'sm' ? 20 : 0}).margin({top: this.currentBreakpoint === 'sm' ? 15 : 0,bottom: this.currentBreakpoint === 'sm' ? 15 : 0}).justifyContent(FlexAlign.SpaceBetween)}build() {if (this.currentBreakpoint === 'sm') {Column() {GridRow() {GridCol({ span: { sm: 4, md: 10 }, offset: { sm: 0, md: 1, lg: 1 } }) {this.CoverImage()}GridCol({ span: { sm: 8, md: 10 }, offset: { sm: 0, md: 2, lg: 2 } }) {this.CoverIntroduction()}GridCol({ span: { sm: 12, md: 10 }, offset: { sm: 0, md: 2, lg: 2 } }) {this.CoverOptions()}}.margin({ left: this.coverMargin, right: this.coverMargin }).padding({ top: this.currentBreakpoint === 'sm' ? 50 : 70 })}} else {Column() {GridRow() {GridCol({ span: { sm: 4, md: 10 }, offset: { sm: 0, md: 1, lg: 1 } }) {this.CoverImage()}GridCol({ span: { sm: 8, md: 10 }, offset: { sm: 0, md: 2, lg: 2 } }) {this.CoverIntroduction()}GridCol({ span: { sm: 12, md: 10 }, offset: { sm: 0, md: 2, lg: 2 } }) {this.CoverOptions()}.margin({top: this.currentBreakpoint === 'sm' ? 15 : 0,bottom: this.currentBreakpoint === 'sm' ? 15 : 0})}.margin({ left: this.coverMargin, right: this.coverMargin }).padding({ top: this.currentBreakpoint === 'sm' ? 50 : 70 })}.height('100%')}}}

1、在sm断点下,封面图片和歌单介绍占满12列,常用操作此时会自动换行显示。
2、在lg和md断点下,封面图片,歌单和常用操作各占一行中显示。

歌单列表

通过List组件的lanes属性实现:在不同断点下,歌单列表的样式一致,但sm和md断点下是歌单列表是单列显示,lg断点下是双列显示,[源码参考]。

搜狗高速浏览器截图20240326151344.png

/*`HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿`* Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { songList } from '../model/SongList'import MyDataSource from '../model/SongModule'@Componentexport default struct PlayList {@StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm'@StorageProp('fontSize') fontSize: number = 0@Consume coverHeight: number@BuilderPlayAll() {Row() {Image($r("app.media.ic_play_all")).height(23).width(23)Text($r('app.string.play_all')).maxLines(1).padding({ left: 10 }).fontColor('#000000').fontSize(this.fontSize)Blank()Image($r('app.media.ic_order_play')).width(24).height(24).margin({ right: 16 })Image($r('app.media.ic_sort_list')).height(24).width(24)}.height(60).width('100%').padding({ left: 12, right: 12 })}@BuilderSongItem(title: string, label: Resource, singer: string) {Row() {Column() {Text(title).fontColor('#000000').fontSize(this.fontSize).margin({ bottom: 4 })Row() {Image(label).width(16).height(16).margin({ right: 4 })Text(singer).opacity(0.38).fontColor('#000000').fontSize(this.fontSize - 4)}}.alignItems(HorizontalAlign.Start)Blank()Image($r('app.media.ic_list_more')).height(24).width(24)}.height(60).width('100%')}build() {Column() {this.PlayAll()Scroll() {List() {LazyForEach(new MyDataSource(songList), item => {ListItem() {Column() {this.SongItem(item.title, item.label, item.singer)Divider().strokeWidth(0.5).color('#000').opacity(0.1)}.width('100%').height(50).padding({ left: 14, right: 14 })}}, item => item.id.toString())}.width('100%').lanes(this.currentBreakpoint === 'lg' ? 2 : 1)}.height('100%').flexGrow(1).flexShrink(1)}.width('100%').height('100%').borderRadius({ topLeft: 20, topRight: 20 }).backgroundColor(Color.White).padding({ bottom: this.currentBreakpoint === 'sm' ? this.coverHeight : 0 })}}
播放控制栏

通过Blank组件实现拉伸能力:在不同断点下,播放控制栏显示的内容完全一致,唯一的区别是歌曲信息与播放控制按钮之间的间距有差异。

总体运行效果

通过在首页Column()中引用上述各组件后,可实现首页的组件整合渲染,即可完成整体页面开发,[源码参考]。

/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { songList } from '../model/SongList'import MyDataSource from '../model/SongModule'@Componentexport default struct PlayList {@StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm'@StorageProp('fontSize') fontSize: number = 0@Consume coverHeight: number@BuilderPlayAll() {Row() {Image($r("app.media.ic_play_all")).height(23).width(23)Text($r('app.string.play_all')).maxLines(1).padding({ left: 10 }).fontColor('#000000').fontSize(this.fontSize)Blank()Image($r('app.media.ic_order_play')).width(24).height(24).margin({ right: 16 })Image($r('app.media.ic_sort_list')).height(24).width(24)}.height(60).width('100%').padding({ left: 12, right: 12 })}@BuilderSongItem(title: string, label: Resource, singer: string) {Row() {Column() {Text(title).fontColor('#000000').fontSize(this.fontSize).margin({ bottom: 4 })Row() {Image(label).width(16).height(16).margin({ right: 4 })Text(singer).opacity(0.38).fontColor('#000000').fontSize(this.fontSize - 4)}}.alignItems(HorizontalAlign.Start)Blank()Image($r('app.media.ic_list_more')).height(24).width(24)}.height(60).width('100%')}build() {Column() {this.PlayAll()Scroll() {List() {LazyForEach(new MyDataSource(songList), item => {ListItem() {Column() {this.SongItem(item.title, item.label, item.singer)Divider().strokeWidth(0.5).color('#000').opacity(0.1)}.width('100%').height(50).padding({ left: 14, right: 14 })}}, item => item.id.toString())}.width('100%').lanes(this.currentBreakpoint === 'lg' ? 2 : 1)}.height('100%').flexGrow(1).flexShrink(1)}.width('100%').height('100%').borderRadius({ topLeft: 20, topRight: 20 }).backgroundColor(Color.White).padding({ bottom: this.currentBreakpoint === 'sm' ? this.coverHeight : 0 })}}

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

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

相关文章

LVM和配额管理

文章目录 一、LVM1.1 LVM概述1.2 LVM的管理命令1.3 创建LVM的过程第一步:先创建物理卷第二步:创建逻辑卷组 / 扩容第三步:创建逻辑卷 / 扩容对ext4文件系统的管理 1.4 删除LVM 二、磁盘配额2.1 磁盘配额概述2.2 磁盘配额命令2.3 磁盘配额设置…

从ZooKeeper切换到ClickHouse-Keeper,藏着怎样的秘密

本文字数:7772;估计阅读时间:20 分钟 作者:博睿数据 李骅宸(太道)& 小叮当 本文在公众号【ClickHouseInc】首发 本系列前两篇内容: 从ES到ClickHouse,Bonree ONE平台更轻更快&a…

vue3学习(三)

前言 继续接上一篇笔记,继续学习的vue的组件化知识,可能需要分2个小节记录。前端大佬请忽略,也可以留下大家的鼓励,感恩! 一、理解组件化 二、组件化知识 1、先上知识点: 2、示例代码 App.vue (主页面) …

数据恢复:手机数据恢复,盘点7个有效手机恢复方法

你知道吗,超过 70% 的智能手机用户都曾有过数据丢失的经历?如果你曾经丢失过手机中的重要文件,别担心,本文有解决办法。在本文中,我们将告诉你如何使用简单的步骤恢复手机中丢失的数据。无论你是不小心删除了文件还是手…

go使用letteravatar生成圆形透明头像图标

官网地址:GitHub - disintegration/letteravatar: Letter avatar generation for Go 我对其中函数改了一下,支持多个字符,效果如下: func TestCreateAvatar(t *testing.T) {GenerateAvatar("Bird Fish", 0, "Bird…

stm32 FLYMCU串口刷机:程序文件不是0x8000000和0x20000000区域的”解决办法。

你想使用串口刷机,用FLYMCU , 刷入的bin 文件是不带地址的,得刷入HEX文件 才可以,因为程序并不知道是从0x8000000开始的, 如果必须得刷入bin 那就得用stm32Cube programmer 这个软件 也可以使用ST-LINK(S…

Word如何绘制三线表及设置磅值

插入表格, 开始 边框 边框和低温 设置磅值 先全部设置为无边框 上边 1.5 0.5 以上内容未完善,请等待作者更新

qmt量化交易策略小白学习笔记第7期【qmt策略之股票快照指标】

qmt策略之股票快照指标 qmt更加详细的教程方法,会持续慢慢梳理。 也可找寻博主的历史文章,搜索关键词查看解决方案 ! 感谢关注,需免费开通量化回测与咨询实盘权限,可以和博主联系! 股票快照指标 提供标…

窄通道、非液压、超续航、更安全,地牛AGV小车诠释高效物流!

agv 在智能时代,替代简单、机械、重复以及重体力工作的智能机器设备成为未来发展的趋势。这种趋势不仅可以提高工作效率和质量,还可以解放人力资源,使其更好地应用于创造性和高级智能任务上。 这不,现在有越来越多的工厂开始使用…

移动云服务器选购指南(图文教程详解)

目录 一、前言 二、基本概念 2.1 定义 2.2 部署形式 2.3 用处 三、主流平台 四、主流产品推荐 4.1 云电脑 4.2 云主机ECS 4.3 弹性公网 IP 五、选购指南 5.1 明确场景 5.2 明确需求 5.3 明确身份 新用户 老用户 5.4 明确时间 5.5 明确教程 六、总结 一、前言…

react 保持组件纯粹

部分 JavaScript 函数是 纯粹 的,这类函数通常被称为纯函数。纯函数仅执行计算操作,不做其他操作。你可以通过将组件按纯函数严格编写,以避免一些随着代码库的增长而出现的、令人困扰的 bug 以及不可预测的行为。但为了获得这些好处&#xff…

WMS仓库管理系统是怎么操作的?WMS操作流程详解

WMS 是仓库管理系统(Warehouse Management System) 的缩写。通过标准化的来料管理、拣配管理、仓库管理,打造实时化、透明化、可视化的仓储管理体系。一款合格的wms系统具有以下优势 提供实时可视性和自动化仓储流程,帮助企业更好地应对复杂的供应链网络…

打造高质感的电子画册,这篇文章告诉你

​在数字化时代,电子画册作为一种全新的视觉传达方式,正逐渐成为各行各业展示形象、传播信息的重要工具。相较于传统的纸质画册,电子画册具有更高的质感、更好的互动性以及更低的制作成本,使得它愈发受到众多企业的青睐。那样怎么…

linux学习(六)

1.网络管理 (1)查看 ifconfig: root用户可以查看网卡状态, 普通用户: /sbin/ifconfig(需要加上命令的完整路径) (2)修改网络配置 通过命令修改网络配置 设置网卡的ip地址;禁用网卡和启用网卡了。 添加网关: (3)网络故障查询 ①ping 检测当前主机和目标主机是…

杨若歆发布最新单曲《迷雾之谜》从啦啦女神到音乐新星的华丽转身

5月28日,台北——杨若歆,这位被粉丝封为"啦啦女神"的多才多艺艺人,近日推出了她的最新单曲《迷雾之谜》,这首歌曲以其空灵的旋律和杨若歆独特的高音,迅速在歌迷中引起了热烈的反响。 杨若歆,身高…

nginx 安全配置

1、前言 前后端分离后,nginx 作为跨域转发工具在日常应用中越来越广泛,它的安全性不能不能忽略。 2、nginx 安装相关说明 2.1 直接下载安装包 在nginx官网下载编译好的安装包,链接地址为nginx: download。如果是linux系统,直接使…

720VR三维立体小程序源码系统 手机电脑端自适应 前后端分离 带完整的安装代码包以及搭建教程

系统概述 720VR 三维立体小程序源码系统是基于先进的技术和理念打造而成的综合性平台。它融合了虚拟现实技术、移动互联网技术以及计算机编程技术,旨在为用户提供沉浸式的 720 度全景体验。 该系统的设计充分考虑了用户的需求,无论是在手机端还是电脑端…

vue-cli2项目中使用scss

前言: 首先要搞清楚Sass和Scss的区别: 实际上Sass和Scss是同一种东西,Scss是 Sass3 引入新的语法,它们都是css预处理器。通常称为Sass,但存在两种不同的语法风格: 文件扩展名:Sass 默认…

探索Python的包与模块:构建项目的基石

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、模块与包的基础认知 1. 模块的定义与创建 2. 包的组织与管理 二、模块与包的进阶使用…

懒人创业秘诀揭秘:加入萤瓴优选项目,普通人也能打开财富大门

创业对于很多人来说,是一个艰难而复杂的过程。然而,时代的发展带来了新的机遇,懒人创业成为了一种趋势。加入萤瓴优选项目,普通人也能轻松打开财富大门。本文将揭秘懒人创业的秘诀,并分析萤瓴优选项目如何帮助普通人实…