0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙OS开发:典型页面场景【一次开发,多端部署】实战(音乐专辑页)

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-05-24 20:33 次阅读

音乐专辑页

本小节将以音乐专辑页为例,介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。

页面设计

音乐专辑页的页面设计如下。

image.png

同样观察音乐专辑的页面设计,不同断点下的页面设计有较多相似的地方。

据此,我们可以将页面分拆为多个组成部分。

  1. 标题栏
  2. 歌单封面
  3. 歌单列表
  4. 播放控制栏
  5. 开发前请熟悉鸿蒙开发指导文档 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]点击或者复制转到。

image.png

标题栏

不同断点下,标题栏始终只显示“返回按钮”、“歌单”以及“更多按钮”,但“歌单”与“更多按钮”之间的间距不同。由于不同断点下标题栏的背景色也有较大差异,因此无法使用拉伸能力实现,此场景更适合使用栅格实现。我们可以将标题栏划分为“返回按钮及歌单”和“更多按钮”两部分,这两部分在不同断点下占据的列数如下图所示。另外,还可以借助OnBreakpointChange事件,调整不同断点下这两部分的背景色。

image.png

@Component
export struct Header {
  @State moreBackgroundColor: Resource = $r('app.color.play_list_cover_background_color');
  build() {
    GridRow() {
      GridCol({span: {sm:6, md: 6, lg:4}}) {
        Row() {
          Image($r('app.media.ic_back')).height('24vp').width('24vp')
        }
        .width('100%')
        .height('50vp')
        .justifyContent(FlexAlign.Start)
        .alignItems(VerticalAlign.Center)
        .padding({left:$r('app.float.default_margin')})
        .backgroundColor($r('app.color.play_list_cover_background_color'))
      }
      GridCol({span: {sm:6, md: 6, lg:8}}) {
        Row() {
          Image($r('app.media.ic_add')).height('24vp').width('24vp')
        }
        .width('100%')
        .height('50vp')
        .justifyContent(FlexAlign.End)
        .alignItems(VerticalAlign.Center)
        .padding({right:$r('app.float.default_margin')})
        .backgroundColor(this.moreBackgroundColor)
      }
    }.onBreakpointChange((currentBreakpoint) = > {
      // 调整不同断点下返回按钮及歌单的背景色
      if (currentBreakpoint === 'sm') {
        this.moreBackgroundColor = $r('app.color.play_list_cover_background_color');
      } else {
        this.moreBackgroundColor = $r('app.color.play_list_songs_background_color');
      }
    }).height('100%').width('100%')
  }
}

歌单封面

歌单封面由封面图片、歌单介绍及常用操作三部分组成,这三部分的布局在md和lg断点下完全相同,但在sm断点下有较大差异。此场景同样可以用栅格实现。

image.png

import { optionList } from '../model/SongList'

@Component
export default struct PlayListCover {
    @State imgHeight: number = 0;
    @StorageProp('coverMargin') coverMargin: number = 0;
    @StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm';
    @StorageProp('fontSize') fontSize: number = 0;

    @Builder
    CoverImage() {
      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)
    }

    @Builder
    CoverIntroduction() {
      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
      })
    }

    @Builder
    CoverOptions() {
      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() {
    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 })
    }
    .height('100%')
    .padding({ top: this.currentBreakpoint === 'sm' ? 50 : 70 })
  }
}

歌单列表

不同断点下,歌单列表的样式基本一致,但sm和md断点下是歌单列表是单列显示,lg断点下是双列显示。可以通过[List组件]的lanes属性实现这一效果。

import { songList } from '../model/SongList';
import MyDataSource from '../model/SongModule'

@Component
export default struct PlayList {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm';
  @StorageProp('fontSize') fontSize: number = 0;
  @Consume coverHeight: number;
   @Builder
  PlayAll() {
    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 })
  }

  @Builder
  SongItem(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() {
              this.SongItem(item.title, item.label, item.singer)
            }
          })
        }
        .width('100%')
        .height('100%')
        // 配置不同断点下歌单列表的列数
        .lanes(this.currentBreakpoint === 'lg' ? 2 : 1)
      }
      .backgroundColor('#fff')
      .margin({ top: 50, bottom: this.currentBreakpoint === 'sm' ? this.coverHeight : 0 })
    }
    .padding({top: 50,bottom: 48})
  }
}

播放控制栏

在不同断点下,播放控制栏显示的内容完全一致,唯一的区别是歌曲信息与播放控制按钮之间的间距有差异,这是典型的拉伸能力的使用场景。

@Component
export default struct Player {
  @StorageProp('fontSize') fontSize: number = 0;
  build() {
    Row() {
      Image($r('app.media.pic_album')).height(32).width(32).margin({right: 12})
      Column() {
        Text($r('app.string.song_name'))
          .fontColor('#000000')
          .fontSize(this.fontSize - 1)
        Row() {
          Image($r('app.media.ic_vip'))
            .height(16)
            .width(16)
            .margin({ right: 4 })
          Text($r('app.string.singer'))
            .fontColor('#000000')
            .fontSize(this.fontSize - 4)
            .opacity(0.38)
        }
      }
      .alignItems(HorizontalAlign.Start)
      // 通过Blank组件实现拉伸能力
      Blank()
      Image($r('app.media.icon_play')).height(26).width(26).margin({right: 16})
      Image($r('app.media.ic_next')).height(24).width(24).margin({right: 16})
      Image($r('app.media.ic_Music_list')).height(24).width(24)
    }
    .width('100%')
    .height(48)
    .backgroundColor('#D8D8D8')
    .alignItems(VerticalAlign.Center)
    .padding({left: 16, right: 16})
  }
}

运行效果

将页面中的四部分组合在一起,即可显示完整的页面。

其中歌单封面和歌单列表这两部分的相对位置,在sm断点下是上下排布,在md和lg断点下是左右排布,也可以用栅格来实现目标效果。

image.png

import PlayListCover from '../common/PlayListCover';
import PlayList from '../common/PlayList';

@Component
export default struct Content {
  // ...
  build() {
    GridRow() {
      // 歌单封面
      GridCol({ span: { xs: 12, sm: 12, md: 6, lg: 4 } }) {
        PlayListCover()
      }
      // 歌单列表
      GridCol({ span: { xs: 12, sm: 12, md: 6, lg: 8 } }) {
        PlayList()
      }
    }
    .height('100%')
  }
}

最后将页面各部分组合在一起即可。

import Header from '../common/Header';
import Player from '../common/Player';
import Content from '../common/Content';

@Entry
@Component
struct Index {
  build() {
    Column() {
      // 标题栏
      Header()
      // 歌单
      Content()
      // 播放控制栏
      Player()
    }.width('100%').height('100%')
  }
}

`HarmonyOSOpenHarmony鸿蒙文档籽料:mau123789是v直接拿`

搜狗高速浏览器截图20240326151450.png
音乐专辑页面的运行效果如下所示。

image.png

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • HarmonyOS
    +关注

    关注

    79

    文章

    1910

    浏览量

    29498
  • OpenHarmony
    +关注

    关注

    24

    文章

    3443

    浏览量

    15332
  • 鸿蒙OS
    +关注

    关注

    0

    文章

    186

    浏览量

    4305
收藏 人收藏

    评论

    相关推荐

    HarmonyOS开发案例:【一次开发多端部署-音乐专辑

    基于自适应和响应式布局,实现一次开发多端部署音乐专辑页面
    的头像 发表于 05-13 16:48 439次阅读
    HarmonyOS<b class='flag-5'>开发</b>案例:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>-<b class='flag-5'>音乐</b><b class='flag-5'>专辑</b>】

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

    本示例使用一次开发多端部署中介绍的自适应布局能力和响应式布局能力进行多设备(或多窗口尺寸)适配,保证应用在不同设备或不同窗口尺寸下可以正常显示。
    的头像 发表于 05-21 14:48 387次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(<b class='flag-5'>音乐</b><b class='flag-5'>专辑</b>主页)

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

    基于自适应和响应式布局,实现一次开发多端部署音乐专辑页面
    的头像 发表于 05-25 16:21 254次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(<b class='flag-5'>音乐</b><b class='flag-5'>专辑</b><b class='flag-5'>页面</b>)

    鸿蒙OS开发:【一次开发多端部署】(视频应用)

    者提供了“一次开发多端部署”的系统能力,让开发者可以基于一次
    的头像 发表于 05-25 16:29 235次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(视频应用)

    鸿蒙OS开发:【一次开发多端部署】(典型布局场景

    虽然不同应用的页面千变万化,但对其进行拆分和分析,页面中的很多布局场景是相似的。本小节将介绍如何借助自适应布局、响应式布局以及常见的容器类组件,实现应用中的典型布局
    的头像 发表于 05-25 16:39 1508次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(<b class='flag-5'>典型</b>布局<b class='flag-5'>场景</b>)

    鸿蒙OS开发典型页面场景一次开发多端部署实战音乐专辑页2)

    本示例使用[一次开发多端部署]中介绍的自适应布局能力和响应式布局能力进行多设备(或多窗口尺寸)适配,保证应用在不同设备或不同窗口尺寸下可以正常显示。
    的头像 发表于 05-25 16:47 1651次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:<b class='flag-5'>典型</b><b class='flag-5'>页面</b><b class='flag-5'>场景</b>【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】<b class='flag-5'>实战</b>(<b class='flag-5'>音乐</b><b class='flag-5'>专辑</b>页2)

    鸿蒙OS开发典型页面场景一次开发多端部署实战(设置典型页面

    本示例展示了设置应用的典型页面,其在小窗口和大窗口有不同的显示效果,体现一次开发多端部署的能力
    的头像 发表于 05-27 09:36 535次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:<b class='flag-5'>典型</b><b class='flag-5'>页面</b><b class='flag-5'>场景</b>【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】<b class='flag-5'>实战</b>(设置<b class='flag-5'>典型</b><b class='flag-5'>页面</b>)

    鸿蒙OS开发典型页面场景一次开发多端部署】(短信)案例介绍

    本章从系统预置的应用中,选择短信应用作为典型的案例,从页面开发和工程结构的角度,介绍"一多"的具体实践。系统的产品形态在不断丰富中,当前主要有默认设备和平板两种产品形态,本章的具体实践也将围绕这两种产品形态展开。
    的头像 发表于 05-28 15:08 488次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:<b class='flag-5'>典型</b><b class='flag-5'>页面</b><b class='flag-5'>场景</b>【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(短信)案例介绍

    鸿蒙OS适用的全场景到底什么意思?

    场景流畅体验、架构级可信安全、跨终端无缝协同以及一次开发多终端部署的要求,鸿蒙应未来而生。”这里说到的全
    发表于 09-25 09:25

    Happ开发后,如何实现多端部署

    做出来后,怎么烧录到它上面?说好的“一次开发多端部署”2、DevEco Studio 开发出来的Happ,它能不能安装到 android的
    发表于 09-10 21:42

    HarmonyOS\"一次开发多端部署\"优秀实践——玩机技巧,码上起航

    的潜在用户群体。个应用要在多类设备上提供统的内容,需要适配不同的屏幕尺寸和硬件,开发成本较高。\"一次开发
    发表于 08-30 18:14

    华为开发者大会2021:软件部总裁龚体 鸿蒙系统 一次开发 多端部署 万物互连

    华为开发者大会2021:鸿蒙系统 一次开发 多端部署 万物互连 在华为
    的头像 发表于 10-22 15:09 4163次阅读
    华为<b class='flag-5'>开发</b>者大会2021:软件部总裁龚体 <b class='flag-5'>鸿蒙</b>系统 <b class='flag-5'>一次</b><b class='flag-5'>开发</b> <b class='flag-5'>多端</b><b class='flag-5'>部署</b> 万物互连

    鸿蒙OS开发:【一次开发多端部署】(多设备自适应能力)简单介绍

    本示例是《一次开发多端部署》的配套示例代码,展示了[页面开发的一多能力],包括自适应布局、响应
    的头像 发表于 05-21 14:59 205次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(多设备自适应能力)简单介绍

    鸿蒙OS开发:【一次开发多端部署】( 设置app页面

    本示例展示了设置应用的典型页面,其在小窗口和大窗口有不同的显示效果,体现一次开发多端部署的能力
    的头像 发表于 05-21 14:56 212次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】( 设置app<b class='flag-5'>页面</b>)

    鸿蒙OS开发典型页面场景一次开发多端部署】(功能开发

    应用开发至少包含两部分工作: UI页面开发和底层功能开发(部分需要联网的应用还会涉及服务端开发)。前面章节介绍了如何解决
    的头像 发表于 05-28 17:32 120次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:<b class='flag-5'>典型</b><b class='flag-5'>页面</b><b class='flag-5'>场景</b>【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(功能<b class='flag-5'>开发</b>)