HarmonyOS掌上记账APP开发实践第98篇:如何按字母分组展示联系人列表
如何按字母分组展示联系人场景说明在通讯录中需要将联系人按照姓氏的首字母进行分组排列从而更方便联系人的查找联系人列表右侧的字母导航可以随列表的滑动而定位到对应字母处同时也可以通过字母导航控制列表跳到指定联系人分组。本例即为大家介绍如何实现上述场景。效果呈现本demo示例最终效果如下实现思路本例涉及的四个关键特性及其实现方案如下联系人按字母分组展示通过List组件显示联系人列表通过ListItemGroup组件实现联系人分组。联系人右侧呈现字母导航使用AlphabetIndexer组件实现字母导航同时通过Stack组件使字母导航浮在联系人列表右侧。滑动联系人列表右侧字母导航随之变动通过List组件的onScrollIndex事件获取到联系人列表的滑动位置并将该位置索引传递给字母导航的selected属性作为字母导航的被选中项。通过右侧字母导航控制联系人列表滑动到指定分组通过字母导航的onSelected事件获取选中字母的索引并将该索引传递给联系人列表的控制器控制列表滑动到指定分组。开发步骤针对上述关键特性具体实现步骤如下1、通过Stack、List、ListItemGroup、AlphabetIndexer等关键组件将UI框架搭建起来。先构建列表数据其中Contact为联系人数据类。contactGroups:object[][...{title:D,contacts:[newContact(Donna,$r(app.media.contact6)),newContact(朵朵,$r(app.media.contact1)),],},...{title:K,contacts:[newContact(孔孔,$r(app.media.contact2)),newContact(康康,$r(app.media.contact3)),],},{title:L,contacts:[newContact(Lisa,$r(app.media.contact4)),newContact(玲玲,$r(app.media.contact5)),],},{title:N,contacts:[newContact(牛牛,$r(app.media.contact6)),newContact(Natasha,$r(app.media.contact1)),],},...]有了列表数据后我们来构建UI框架关键代码如下EntryComponentstruct ContactList{...// 自定义组件groupHeader作为ListItemGroup的头部组件即A、B、C等字母列表项BuildergroupHeader(titleLetter:string){Text(titleLetter).fontSize(20).backgroundColor(#fff1f3f5).width(100%).padding(5)}// 创建字母列表作为字母导航的内容privatealphabets:string[][A,B,D,G,K,L,N,X];build(){Stack({alignContent:Alignment.End}){List(){// 循环渲染列表内容ForEach(this.contactGroups,contactGroup{// 采用ListItemGroup对联系人进行分组将groupHeader作为ListItemGroup的头部组件ListItemGroup({header:this.groupHeader(contactGroup.title)}){ForEach(contactGroup.contacts,contact{ListItem(){Column(){Row(){Image(contact.icon)...Text(contact.name)}...Divider().color(#fff1f3f5)}...}})}})}...// 使用AlphabetIndexer组件实现右侧字母导航AlphabetIndexer({arrayValue:this.alphabets,selected:0})...}}}完成上述代码我们的框架就搭建起来了如图2、接下来为UI框架添加逻辑控制。首先通过List的onScrollIndex事件获取到列表滑动位置的索引并将索引同步给右侧字母表的selected属性从而在滑动联系人时使右侧字母导航随之变动关键代码如下...// 创建动态变量用于指定字母导航的选择项StateselectedIndex:number0;...build(){Stack({alignContent:Alignment.End}){List({scroller:this.listScroller}){ForEach(this.contactGroups,contactGroup{ListItemGroup({header:this.groupHeader(contactGroup.title)}){ForEach(contactGroup.contacts,contact{ListItem(){...}})}})}...// 获取联系人列表滑动位置的索引并将索引通过selectedIndex同步给右侧字母导航.onScrollIndex((firstIndex:number){this.selectedIndexfirstIndex})AlphabetIndexer({arrayValue:this.alphabets,selected:0})...// 指定字母导航的选择项为selectedIndex完成跟联系人列表的同步.selected(this.selectedIndex)...}}至此当我们滑动联系人列表时就可以让右侧字母导航随之变动了。效果如下3、最后我们通过AlphabetIndexer组件的onSelect事件获取到字母导航选择项的索引然后通过List组件的scroller控制器控制联系人列表滑动到相同的索引处从而实现通过右侧字母导航控制联系人列表滑动到指定分组。关键代码如下...StateselectedIndex:number0;// 创建List组件的scroller控制器listScroller用于控制联系人列表的滑动位置privatelistScroller:ScrollernewScroller()...build(){Stack({alignContent:Alignment.End}){// 将scroller控制器绑定到List组件List({scroller:this.listScroller}){ForEach(this.contactGroups,contactGroup{ListItemGroup({header:this.groupHeader(contactGroup.title)}){ForEach(contactGroup.contacts,contact{ListItem(){...}})}})}...AlphabetIndexer({arrayValue:this.alphabets,selected:0})...// 获取字母导航中选中字母的索引值并通过listScroller控制列表滑动到对应索引位置.onSelect((index:number){this.listScroller.scrollToIndex(index)})...}}至此当我们在右侧字母导航选择某个字母时就可以控制联系人列表跳转到指定分组了效果如下完整代码通过上述步骤我们已经完成了整个示例的开发现提供本示例的完整代码供大家参考联系人数据类代码// ListModel.etsexportdefaultclassContact{name:string;icon:Resource;constructor(name:string,icon:Resource){this.namenamethis.iconicon}}案例主代码// Contact.etsimportContactfrom../model/ListModelEntryComponentstruct ContactList{// 联系人列表数据contactGroups:object[][{title:A,contacts:[newContact(艾薇而,$r(app.media.contact1)),newContact(安琪,$r(app.media.contact2)),newContact(Angela,$r(app.media.contact3)),],},{title:B,contacts:[newContact(Bobe,$r(app.media.contact4)),newContact(勃勃,$r(app.media.contact5)),],},{title:D,contacts:[newContact(Donna,$r(app.media.contact6)),newContact(朵朵,$r(app.media.contact1)),],},{title:G,contacts:[newContact(Gavin,$r(app.media.contact4)),newContact(果味,$r(app.media.contact1)),],},{title:K,contacts:[newContact(孔孔,$r(app.media.contact2)),newContact(康康,$r(app.media.contact3)),],},{title:L,contacts:[newContact(Lisa,$r(app.media.contact4)),newContact(玲玲,$r(app.media.contact5)),],},{title:N,contacts:[newContact(牛牛,$r(app.media.contact6)),newContact(Natasha,$r(app.media.contact1)),],},{title:X,contacts:[newContact(小可爱,$r(app.media.contact2)),newContact(徐总是,$r(app.media.contact3)),newContact(璇璇,$r(app.media.contact3)),newContact(欣欣,$r(app.media.contact3)),],},]// 自定义组件groupHeader作为ListItemGroup的头部组件即A、B、C等字母列表项BuildergroupHeader(titleLetter:string){Text(titleLetter).fontSize(20).backgroundColor(#fff1f3f5).width(100%).padding(5)}// 创建字母列表作为字母导航的内容privatealphabets:string[][A,B,D,G,K,L,N,X];// 创建动态变量用于指定字母导航的选择项StateselectedIndex:number0;// 创建List组件的scroller控制器listScroller用于控制联系人列表的滑动位置privatelistScroller:ScrollernewScroller()build(){Stack({alignContent:Alignment.End}){// 将scroller控制器绑定到List组件List({scroller:this.listScroller}){// 循环渲染列表内容ForEach(this.contactGroups,contactGroup{// 采用ListItemGroup对联系人进行分组将groupHeader作为ListItemGroup的头部组件ListItemGroup({header:this.groupHeader(contactGroup.title)}){ForEach(contactGroup.contacts,contact{ListItem(){Column(){Row(){Image(contact.icon).width(35).height(35).margin(10)Text(contact.name)}.width(100%)Divider().color(#fff1f3f5)}.justifyContent(FlexAlign.Start)}})}})}.width(100%).height(100%).scrollBar(BarState.Auto)// 获取联系人列表滑动位置的索引并将索引通过selectedIndex同步给右侧字母导航.onScrollIndex((firstIndex:number){this.selectedIndexfirstIndex})// 使用AlphabetIndexer组件实现右侧字母导航AlphabetIndexer({arrayValue:this.alphabets,selected:0}).margin({right:10}).itemSize(25).font({size:15})// 指定字母导航的选择项为selectedIndex完成跟联系人列表的同步.selected(this.selectedIndex)// 获取选中字母的索引值通过listScroller控制列表滑动到对应索引位置.onSelect((index:number){this.listScroller.scrollToIndex(index)})}}}参考创建列表

相关新闻

STM32与LENA-R8实现全球物联网定位与通信方案

STM32与LENA-R8实现全球物联网定位与通信方案

1. 项目背景与核心组件介绍 在物联网和远程监控领域,全球连接和精确定位是两大核心需求。LENA-R8模块与STM32F446RE微控制器的组合,为开发者提供了一个高效可靠的解决方案。这个项目展示了如何利用这两款硬件实现全球范围内的数据传输和米级定位精度。 …

2026/10/15 0:28:36 阅读更多 →
LTE Cat 1bis物联网模块与PIC18F86K90的硬件设计与通信实现

LTE Cat 1bis物联网模块与PIC18F86K90的硬件设计与通信实现

1. 项目背景与硬件选型考量 在物联网设备开发领域,LTE Cat 1bis技术因其适中的数据传输速率和较低的功耗特性,正成为智能电表、资产追踪和工业传感器等应用的理想选择。LEXI-R10401D作为一款符合3GPP Release 14标准的通信模块,其最大下行速率…

2026/10/15 14:19:19 阅读更多 →
终极视频修复指南:如何使用Untrunc工具快速恢复损坏的MP4文件

终极视频修复指南:如何使用Untrunc工具快速恢复损坏的MP4文件

终极视频修复指南:如何使用Untrunc工具快速恢复损坏的MP4文件 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc 你是否曾经因为视频文件损坏而失去珍贵的回…

2026/10/15 14:19:34 阅读更多 →

最新新闻

STM32四轴飞控从零实现:MPU6050姿态解算与串级PID完整指南

STM32四轴飞控从零实现:MPU6050姿态解算与串级PID完整指南

简介:压缩包是一份基于STM32微控制器实现的无人机飞控工程,面向嵌入式飞控开发初学者,完整展示从底层外设驱动到上层控制算法的代码组织方式。文件共212个,以C源程序与头文件为主(40个C源文件、42个头文件)…

2026/10/16 4:14:16 阅读更多 →
从真实主板拆解看懂示波器原理:信号链、触发与采样全解析

从真实主板拆解看懂示波器原理:信号链、触发与采样全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 4:14:16 阅读更多 →
Canvas时间轴开发:从坐标映射到性能优化的工程实践

Canvas时间轴开发:从坐标映射到性能优化的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 4:14:16 阅读更多 →
HBase线上调优三支柱:读写分离、RSgroup与流量控制协同实践

HBase线上调优三支柱:读写分离、RSgroup与流量控制协同实践

1. 这不是教科书里的HBase调优,是线上血泪换来的三把刀HBase线上生产调优建议(读写分离、RSgroup、流量控制)——这个标题里藏着的不是几个技术名词的堆砌,而是某电商大促期间凌晨三点被电话叫醒、盯着监控面板手心冒汗的真实场景…

2026/10/16 4:14:16 阅读更多 →
为什么LSM树写比读快?存储引擎核心原理深度解析

为什么LSM树写比读快?存储引擎核心原理深度解析

1. 黑胶唱片的启示:介质特性决定了你优化什么1.1 为什么黑胶适合“一次刻录,万次播放”老式黑胶唱片有个很有意思的特性:压制过程极其昂贵,一块母盘要经过电铸、制版、压片多道工序,生产线一旦开动,成本几乎…

2026/10/16 4:14:16 阅读更多 →
SQL执行顺序全解析:从FROM到LIMIT的数据库优化实战

SQL执行顺序全解析:从FROM到LIMIT的数据库优化实战

在数据库面试题里,“SQL 执行顺序”几乎是一道必问题,很多人在简历上写着“精通 SQL”,但遇到这个问题还是会卡壳。说实话,这个问题不只是拿来应付面试的,它直接决定了你排查 SQL 报错、优化慢查询时的思路是否清晰。我…

2026/10/16 4:13:16 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →