暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

137. [HarmonyOS NEXT 实战案例七:List系列] 多列列表组件实战:打造精美应用推荐页 基础篇

原创 若城 2025-06-30
518

[HarmonyOS NEXT 实战案例七:List系列] 多列列表组件实战:打造精美应用推荐页 基础篇

项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

一、多列列表基础介绍

在HarmonyOS NEXT应用开发中,多列列表是一种常见的UI布局方式,特别适合展示网格状的内容,如应用商店、图片库、商品展示等。多列列表可以在有限的屏幕空间内高效地展示更多内容,提升用户体验。

1.1 多列列表的特点

特点 说明
网格布局 内容以网格形式排列,可同时展示多个列表项
高效利用空间 在同一屏幕空间内可展示更多内容
灵活的列数设置 可根据屏幕大小和内容特点设置不同的列数
支持分割线 可添加网格分割线,使界面更加清晰
自适应布局 可根据屏幕方向和大小自动调整布局

1.2 多列列表的实现方式

在HarmonyOS NEXT中,实现多列列表主要有两种方式:

  1. 使用List组件的lanes属性:通过设置List组件的lanes属性,可以将列表项排列为多列布局。
  2. 使用Grid组件:Grid组件专门用于创建网格布局,适合更复杂的网格需求。

在本教程中,我们将重点介绍使用List组件的lanes属性实现多列列表。

二、多列列表实战案例

在本案例中,我们将实现一个应用推荐页面,以多列网格的形式展示应用信息,包括应用图标、名称和下载量。

2.1 数据模型定义

首先,我们需要定义应用的数据模型:

interface AppType { name: string; icon: Resource; downloads: string; }

这个接口定义了应用的三个属性:名称、图标和下载量。其中图标使用Resource类型,表示资源引用。

2.2 数据准备

接下来,我们准备应用数据:

private apps: AppType[] = [ { name: '音乐播放器', icon: $r("app.media.music_icon"), downloads: '1000万+' }, { name: '视频播放器', icon: $r('app.media.video_icon_videos'), downloads: '500万+' }, { name: '图片编辑器', icon: $r('app.media.photo_icon'), downloads: '300万+' }, { name: '日历', icon: $r('app.media.calendar'), downloads: '800万+' }, { name: '天气', icon: $r('app.media.active_weather_icon'), downloads: '1200万+' }, { name: '计算器', icon: $r('app.media.mobile_calculator_ap'), downloads: '600万+' }, { name: '备忘录', icon: $r("app.media.note_icon"), downloads: '400万+' }, { name: '地图', icon: $r('app.media.map_icon2'), downloads: '900万+' }, { name: '电子书', icon: $r("app.media.Facebook_icon_03"), downloads: '200万+' }, { name: '购物', icon: $r('app.media.Shopping_icon'), downloads: '700万+' }, { name: '游戏中心', icon: $r("app.media.game_icon"), downloads: '1500万+' }, { name: '健康', icon: $r("app.media.dcc_health_icon"), downloads: '350万+' }, ]

我们创建了一个包含12个应用的数组,每个应用都有名称、图标资源和下载量信息。

2.3 页面结构设计

整个页面采用垂直布局,包含标题栏、应用列表和底部导航栏三部分:

build() { Column() { // 标题栏 Row() { Text('应用推荐') .fontSize(24) .fontWeight(FontWeight.Bold) } .width('100%') .height(56) .padding({ left: 16 }) .backgroundColor('#F1F3F5') // 多列应用列表 List() { // 列表内容 } .width('100%') .layoutWeight(1) .lanes(3) // 设置为3列布局 .divider({ // 设置网格分割线 strokeWidth: 1, color: '#E5E5E5', startMargin: 8, endMargin: 8 }) // 底部导航栏 Row() { // 导航栏内容 } .width('100%') .height(60) .padding({ top: 8, bottom: 8 }) .backgroundColor('#FFFFFF') .borderColor('#E5E5E5') .borderWidth({ top: 1 }) } .width('100%') .height('100%') .backgroundColor('#FFFFFF') }

在这个结构中:

  • 使用Column作为根容器,占满整个屏幕
  • 顶部是一个Row容器,作为标题栏,包含标题文本
  • 中间是List组件,用于显示应用列表,设置lanes(3)使其成为3列布局
  • 底部是一个Row容器,作为导航栏

2.4 列表项实现

接下来,我们实现列表项的内容:

List() { ForEach(this.apps, (app:AppType) => { ListItem() { Column() { // 应用图标 Image(app.icon) .width(60) .height(60) .borderRadius(12) // 应用名称 Text(app.name) .width(100) .fontSize(14) .margin({ top: 8 }) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) // 下载量 Text(app.downloads) .width(100) .fontSize(12) .fontColor('#666666') .margin({ top: 4 }) } .alignItems(HorizontalAlign.Center) .width('100%') .padding(12) } .width('33%') // 每个项目占用1/3的宽度 .padding(8) }) }

在这段代码中:

  1. 使用ForEach遍历apps数组,为每个应用创建一个ListItem
  2. 每个ListItem包含一个Column布局,用于垂直排列应用图标、名称和下载量
  3. 应用图标使用Image组件,设置为圆角矩形(通过borderRadius实现)
  4. 应用名称和下载量使用Text组件,设置不同的字体大小和颜色
  5. 设置ListItem的宽度为’33%',使每行显示3个应用

2.5 底部导航栏实现

最后,我们实现底部导航栏:

Row() { Column() { Image($r('app.media.01')) .width(24) .height(24) Text('首页') .fontSize(12) .margin({ top: 4 }) } .layoutWeight(1) Column() { Image($r('app.media.02')) .width(24) .height(24) Text('分类') .fontSize(12) .margin({ top: 4 }) } .layoutWeight(1) Column() { Image($r('app.media.03')) .width(24) .height(24) Text('排行') .fontSize(12) .margin({ top: 4 }) .fontColor('#007DFF') } .layoutWeight(1) Column() { Image($r('app.media.04')) .width(24) .height(24) Text('我的') .fontSize(12) .margin({ top: 4 }) } .layoutWeight(1) }

在这段代码中:

  1. 使用Row作为导航栏的容器,包含4个Column子容器
  2. 每个Column代表一个导航项,包含一个图标和一个文本
  3. 使用layoutWeight(1)使4个导航项平均分配空间
  4. 为当前选中的导航项(排行)设置特殊的文本颜色

三、完整代码解析

让我们来看一下完整的代码实现:

@Component export struct MultiColumnList { // 应用数据 private apps: AppType[] = [ { name: '音乐播放器', icon: $r("app.media.music_icon"), downloads: '1000万+' }, { name: '视频播放器', icon: $r('app.media.video_icon_videos'), downloads: '500万+' }, { name: '图片编辑器', icon: $r('app.media.photo_icon'), downloads: '300万+' }, { name: '日历', icon: $r('app.media.calendar'), downloads: '800万+' }, { name: '天气', icon: $r('app.media.active_weather_icon'), downloads: '1200万+' }, { name: '计算器', icon: $r('app.media.mobile_calculator_ap'), downloads: '600万+' }, { name: '备忘录', icon: $r("app.media.note_icon"), downloads: '400万+' }, { name: '地图', icon: $r('app.media.map_icon2'), downloads: '900万+' }, { name: '电子书', icon: $r("app.media.Facebook_icon_03"), downloads: '200万+' }, { name: '购物', icon: $r('app.media.Shopping_icon'), downloads: '700万+' }, { name: '游戏中心', icon: $r("app.media.game_icon"), downloads: '1500万+' }, { name: '健康', icon: $r("app.media.dcc_health_icon"), downloads: '350万+' }, ] build() { Column() { // 标题栏 Row() { Text('应用推荐') .fontSize(24) .fontWeight(FontWeight.Bold) } .width('100%') .height(56) .padding({ left: 16 }) .backgroundColor('#F1F3F5') // 多列应用列表 List() { ForEach(this.apps, (app:AppType) => { ListItem() { Column() { // 应用图标 Image(app.icon) .width(60) .height(60) .borderRadius(12) // 应用名称 Text(app.name) .width(100) .fontSize(14) .margin({ top: 8 }) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) // 下载量 Text(app.downloads) .width(100) .fontSize(12) .fontColor('#666666') .margin({ top: 4 }) } .alignItems(HorizontalAlign.Center) .width('100%') .padding(12) } .width('33%') // 每个项目占用1/3的宽度 .padding(8) }) } .width('100%') .layoutWeight(1) .lanes(3) // 设置为3列布局 .divider({ // 设置网格分割线 strokeWidth: 1, color: '#E5E5E5', startMargin: 8, endMargin: 8 }) // 底部导航栏 Row() { Column() { Image($r('app.media.01')) .width(24) .height(24) Text('首页') .fontSize(12) .margin({ top: 4 }) } .layoutWeight(1) Column() { Image($r('app.media.02')) .width(24) .height(24) Text('分类') .fontSize(12) .margin({ top: 4 }) } .layoutWeight(1) Column() { Image($r('app.media.03')) .width(24) .height(24) Text('排行') .fontSize(12) .margin({ top: 4 }) .fontColor('#007DFF') } .layoutWeight(1) Column() { Image($r('app.media.04')) .width(24) .height(24) Text('我的') .fontSize(12) .margin({ top: 4 }) } .layoutWeight(1) } .width('100%') .height(60) .padding({ top: 8, bottom: 8 }) .backgroundColor('#FFFFFF') .borderColor('#E5E5E5') .borderWidth({ top: 1 }) } .width('100%') .height('100%') .backgroundColor('#FFFFFF') } }

3.1 代码结构分析

部分 说明
@Component 组件装饰器,表明这是一个自定义组件
private apps 私有属性,存储应用数据
build() 组件的构建函数,定义组件的UI结构
Column 根容器,垂直排列子元素
Row 标题栏和底部导航栏容器,水平排列子元素
List 列表容器,用于展示应用列表
ForEach 循环构建器,遍历应用数据
ListItem 列表项容器,定义每个应用的布局

3.2 样式设置分析

在这个案例中,我们使用了多种样式设置来美化界面:

  1. 尺寸设置:

    • 使用width(‘100%’)和height(‘100%’)使组件占满父容器
    • 使用layoutWeight(1)使List组件占据剩余空间
    • 设置具体的像素值,如height(56)、width(60)等
    • 使用width(‘33%’)设置列表项宽度为容器的1/3
  2. 边距和填充:

    • 使用padding设置内边距
    • 使用margin设置外边距
  3. 颜色和背景:

    • 设置背景颜色backgroundColor
    • 设置文本颜色fontColor
    • 设置边框颜色borderColor
  4. 文本样式:

    • 设置字体大小fontSize
    • 设置字体粗细fontWeight
    • 使用maxLines和textOverflow处理文本溢出
  5. 特殊效果:

    • 使用borderRadius设置圆角效果
    • 使用divider设置分割线
    • 使用borderWidth设置边框宽度

3.3 多列列表关键属性

实现多列列表的关键在于以下几个属性:

  1. lanes属性:

    .lanes(3) // 设置为3列布局

    lanes属性指定了列表的列数,在本例中设置为3,表示列表项将排列为3列。

  2. 列表项宽度:

    .width('33%') // 每个项目占用1/3的宽度

    为了使列表项能够正确排列,需要设置每个ListItem的宽度。在3列布局中,每个列表项的宽度设置为’33%',表示占用容器宽度的1/3。

  3. 网格分割线:

    .divider({ // 设置网格分割线 strokeWidth: 1, color: '#E5E5E5', startMargin: 8, endMargin: 8 })

    divider属性用于设置列表的分割线。在多列列表中,分割线会形成网格状,使界面更加清晰。

总结

在本篇教程中,我们学习了如何使用HarmonyOS NEXT的List组件的lanes属性创建多列列表,实现了一个应用推荐页面。我们从数据模型定义、页面结构设计、列表项实现到底部导航栏实现,全面讲解了多列列表的实现过程。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论