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

145.[HarmonyOS NEXT 实战案例七 :List系列] 可选择列表基础篇

原创 若城 2025-06-30
254

[HarmonyOS NEXT 实战案例七 :List系列] 可选择列表基础篇

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

效果演示

在移动应用开发中,可选择列表是一种常见且实用的交互模式,它允许用户从列表中选择一个或多个项目进行批量操作。本教程将详细讲解如何在HarmonyOS NEXT中实现一个功能完善的可选择列表,以文件管理应用为例,展示如何创建、管理和操作可选择列表。

一、可选择列表概述

可选择列表是List组件的一种特殊应用场景,它具有以下特点:

  1. 多选功能:允许用户同时选择多个列表项
  2. 选择模式切换:可以在普通浏览模式和选择模式之间切换
  3. 批量操作:对选中的项目执行批量操作,如删除、移动、分享等
  4. 全选/取消全选:提供快捷方式选择或取消选择所有项目
  5. 视觉反馈:通过UI变化清晰地指示当前选中的项目

二、数据模型设计

首先,我们需要定义文件数据的接口和示例数据:

interface FileType { id: number, name: string, type: string, size: string, date: string, icon: Resource }

这个接口定义了文件的基本属性:

  • id:文件的唯一标识符
  • name:文件名称
  • type:文件类型(如docx、xlsx、pdf等)
  • size:文件大小
  • date:修改日期
  • icon:文件图标资源

然后,我们创建示例文件数据:

private files: FileType[] = [ { id: 1, name: '项目计划.docx', type: 'docx', size: '2.5MB', date: '2023-10-15', icon: $r('app.media.big26') }, { id: 2, name: '财务报表.xlsx', type: 'xlsx', size: '1.8MB', date: '2023-10-14', icon: $r('app.media.big25') }, // 更多文件... ]

三、状态管理

为了管理可选择列表的状态,我们需要定义以下状态变量:

// 选中的文件ID列表 @State selectedIds: number[] = [] // 是否处于选择模式 @State isSelectMode: boolean = false
  • selectedIds:存储当前选中的文件ID列表
  • isSelectMode:标记当前是否处于选择模式

四、核心功能实现

1. 切换选择模式

toggleSelectMode() { this.isSelectMode = !this.isSelectMode if (!this.isSelectMode) { this.selectedIds = [] } }

这个方法用于切换选择模式的开启和关闭。当退出选择模式时,会清空已选择的项目。

2. 切换选择状态

toggleSelection(id: number) { const index = this.selectedIds.indexOf(id) if (index === -1) { this.selectedIds.push(id) } else { this.selectedIds.splice(index, 1) } }

这个方法用于切换单个文件的选择状态:如果文件未被选中,则添加到选中列表;如果已被选中,则从列表中移除。

3. 全选和取消全选

// 全选 selectAll() { this.selectedIds = this.files.map(file => file.id) } // 取消全选 deselectAll() { this.selectedIds = [] }

这两个方法分别用于全选和取消全选操作。

4. 获取文件图标

getFileIcon(type: string): Resource { switch (type) { case 'docx': return $r('app.media.big26') case 'xlsx': return $r('app.media.big25') // 其他文件类型... default: return $r('app.media.big20') } }

这个方法根据文件类型返回对应的图标资源。

五、UI构建

1. 整体布局

build() { Column() { // 标题栏 Row() { /* ... */ } // 文件列表 List() { /* ... */ } // 底部操作栏(选择模式下显示) if (this.isSelectMode && this.selectedIds.length > 0) { Row() { /* ... */ } } } .width('100%') .height('100%') .backgroundColor('#FFFFFF') }

整体布局采用Column容器,包含三个主要部分:标题栏、文件列表和底部操作栏(仅在选择模式下且有选中项时显示)。

2. 标题栏实现

标题栏会根据当前是否处于选择模式显示不同的内容:

Row() { if (this.isSelectMode) { // 选择模式下的标题栏 Image($r('app.media.big2')) .width(24) .height(24) .onClick(() => this.toggleSelectMode()) Text(`已选择 ${this.selectedIds.length} 项`) .fontSize(18) .fontWeight(FontWeight.Medium) .margin({ left: 16 }) Blank() Button(this.selectedIds.length === this.files.length ? '取消全选' : '全选') .fontSize(14) .fontColor('#007DFF') .backgroundColor('transparent') .onClick(() => { if (this.selectedIds.length === this.files.length) { this.deselectAll() } else { this.selectAll() } }) } else { // 普通模式下的标题栏 Text('文件') .fontSize(24) .fontWeight(FontWeight.Bold) Blank() Image($r('app.media.01')) .width(24) .height(24) .margin({ right: 16 }) Image($r('app.media.02')) .width(24) .height(24) .margin({ right: 16 }) .onClick(() => this.toggleSelectMode()) } } .width('100%') .height(56) .padding({ left: 16, right: 16 }) .backgroundColor('#F1F3F5')
  • 在选择模式下:显示返回按钮、已选择项数量和全选/取消全选按钮
  • 在普通模式下:显示标题和操作按钮,包括进入选择模式的按钮

3. 文件列表实现

List() { ForEach(this.files, (file: FileType) => { ListItem() { Row() { if (this.isSelectMode) { // 选择框 Checkbox({ name: file.id.toString() }) .select(this.selectedIds.includes(file.id)) .margin({ right: 16 }) .onChange((value) => { this.toggleSelection(file.id) }) } // 文件图标 Image(this.getFileIcon(file.type)) .width(40) .height(40) .margin({ right: 16 }) // 文件信息 Column() { Text(file.name) .fontSize(16) .fontWeight(FontWeight.Medium) Row() { Text(file.size) .fontSize(14) .fontColor('#666666') Text(file.date) .fontSize(14) .fontColor('#666666') .margin({ left: 16 }) } .margin({ top: 4 }) } .alignItems(HorizontalAlign.Start) .layoutWeight(1) if (!this.isSelectMode) { // 更多操作按钮 Image($r('app.media.game_icon')) .width(24) .height(24) } } .width('100%') .padding({ left: 16, right: 16, top: 12, bottom: 12 }) .onClick(() => { if (this.isSelectMode) { this.toggleSelection(file.id) } }) } .height(72) .backgroundColor(this.selectedIds.includes(file.id) ? '#F0F7FF' : '#FFFFFF') }) } .width('100%') .layoutWeight(1) .divider({ // 设置分割线 strokeWidth: 1, color: '#E5E5E5', startMargin: this.isSelectMode ? 72 : 72, endMargin: 16 }) .multiSelectable(this.isSelectMode) // 启用选择模式

文件列表的关键点:

  1. 使用ForEach遍历文件数据,为每个文件创建一个ListItem
  2. 在选择模式下显示Checkbox,并绑定选择状态和变更事件
  3. 根据文件是否被选中,设置不同的背景色以提供视觉反馈
  4. 使用multiSelectable属性启用List的多选功能
  5. 设置分割线样式,并根据是否处于选择模式调整起始边距

4. 底部操作栏实现

if (this.isSelectMode && this.selectedIds.length > 0) { Row() { Button('删除') .width(100) .height(40) .backgroundColor('#F44336') .margin({ right: 16 }) Button('移动') .width(100) .height(40) .backgroundColor('#007DFF') .margin({ right: 16 }) Button('分享') .width(100) .height(40) .backgroundColor('#4CAF50') } .width('100%') .height(72) .padding(16) .justifyContent(FlexAlign.Center) .backgroundColor('#FFFFFF') .borderColor('#E5E5E5') .borderWidth({ top: 1 }) }

底部操作栏仅在选择模式下且有选中项时显示,包含删除、移动和分享三个操作按钮。

六、关键技术点分析

1. 多选功能的实现

多选功能主要通过以下几个方面实现:

  • 使用@State selectedIds: number[]存储选中项的ID
  • 通过toggleSelection方法管理选中状态
  • 使用List组件的multiSelectable属性启用多选功能
  • 通过Checkbox组件提供选择界面

2. 模式切换的实现

模式切换主要通过@State isSelectMode: boolean状态变量和toggleSelectMode方法实现。当模式切换时,UI会相应地变化:

  • 标题栏内容变化
  • 列表项中显示/隐藏选择框
  • 底部操作栏的显示/隐藏

3. 视觉反馈的实现

为了提供良好的用户体验,代码中实现了多种视觉反馈:

  • 选中项的背景色变化:.backgroundColor(this.selectedIds.includes(file.id) ? '#F0F7FF' : '#FFFFFF')
  • 已选择项数量的显示:Text(已选择 ${this.selectedIds.length} 项)
  • 全选/取消全选按钮文本的动态变化:Button(this.selectedIds.length === this.files.length ? '取消全选' : '全选')

七、代码结构与样式设置

组件部分 主要功能 样式设置
Column 整体容器 宽高100%,白色背景
标题栏Row 显示标题和操作按钮 高56px,左右内边距16px,浅灰背景
List 显示文件列表 宽100%,弹性布局权重1,带分割线
ListItem 单个文件项 高72px,选中时背景色变化
底部Row 批量操作按钮 高72px,内边距16px,居中对齐,顶部边框

八、总结

本教程详细讲解了如何在HarmonyOS NEXT中实现一个功能完善的可选择列表 ,通过本教程,你应该能够掌握HarmonyOS NEXT中可选择列表的基本实现方法,并能够应用到自己的项目中。在进阶篇中,我们将探讨如何增强可选择列表的功能,如拖拽排序、搜索过滤、分类显示等高级特性。

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

评论