Compose 一个联系人索引列表实现

news2024/10/9 13:54:06

一、前言

该功能是一个左侧为字符索引列表,右侧为联系人列表的实现,点击左侧字符索引可以自动滑动到对应联系人条目。该功能代码实现绝大多数有通义灵码完成。实现效果如下:
在这里插入图片描述

关键代码

data class Contact(val name: String)

class ContactsPage {
    val contacts = listOf(
        Contact("Alice"),
        Contact("Bob"),
        Contact("Charlie"),
        Contact("David"),
        Contact("Eve"),
        Contact("Frank"),
        Contact("Grace"),
        Contact("Heidi"),
        Contact("Ivan"),
        Contact("John"),
        Contact("Karen"),
        Contact("Larry"),
        Contact("Mary"),
        Contact("Nancy"),
        Contact("Olivia"),
        Contact("Paul"),
        Contact("Quincy"),
        Contact("Rachel"),
        Contact("Steve"),
        Contact("Tom"),
        Contact("Ursula"),
        Contact("Victor"),
        Contact("Wendy"),
        Contact("Xavier"),
        Contact("Yolanda"),
        Contact("Zoe")
    )

    fun alphabetIndexer(contact: Contact) = contact.name.first().toString().uppercase()

    @Composable
    fun IndexedContactsList(contacts: List<Contact>) {
        val indexer = { contact: Contact -> alphabetIndexer(contact) }
        val sections = contacts.groupBy(indexer)
        val entries = sections.entries.toList()

        // 记录每个字母索引的位置
        val letterPositions = remember { mutableMapOf<String, Int>() }
        val listState = remember { LazyListState() }

        // 计算每个字母索引的位置
        var currentLetter = ""
        for ((position, contact) in contacts.withIndex()) {
            val letter = indexer(contact)
            if (letter != currentLetter) {
                letterPositions[letter] = position
                currentLetter = letter
            }
        }
        val coroutineScope = rememberCoroutineScope()
        Row(
            modifier = Modifier.fillMaxSize()
        ) {
            // 右侧字母索引列表
            LazyColumn(
                modifier = Modifier
                    .weight(0.2f) // 设置宽度比例
                    .fillMaxHeight()
                    .padding(8.dp)
            ) {
                itemsIndexed(entries) { index, entry ->
                    Text(
                        text = entry.key,
                        modifier = Modifier
                            .fillMaxWidth()
                            .clickable {
                                /* Handle click */
                                // 点击字母索引时滚动到对应位置
                                coroutineScope.launch {
                                    listState.animateScrollToItem(letterPositions[entry.key] ?: 0)
                                }
                            }
                            .padding(vertical = 8.dp),
                        style = MaterialTheme.typography.subtitle1,
                        color = Color.Gray
                    )
                }
            }

            // 左侧联系人列表
            LazyColumn(
                state = listState,
                modifier = Modifier
                    .weight(0.8f) // 设置宽度比例
                    .fillMaxHeight()
                    .padding(8.dp)
            ) {
                itemsIndexed(contacts) { index, contact ->
                    val letter = indexer(contact)
                    if (index == 0 || indexer(contacts[index - 1]) != letter) {
                        Text(
                            text = letter,
                            modifier = Modifier.padding(
                                start = 16.dp,
                                top = 8.dp,
                                end = 16.dp,
                                bottom = 4.dp
                            ),
                            style = MaterialTheme.typography.subtitle1,
                            color = Color.Gray
                        )
                    }
                    Text(
                        text = contact.name,
                        modifier = Modifier
                            .fillMaxWidth()
                            .clickable { /* Handle click */ }
                            .padding(horizontal = 16.dp, vertical = 8.dp),
                        style = MaterialTheme.typography.body1
                    )
                }
            }
        }
    }

    @Preview(showBackground = true)
    @Composable
    fun PreviewIndexedContactsList() {
        MaterialTheme {
            IndexedContactsList(contacts)
        }
    }
}

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

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

相关文章

unix中如何申请进程调度的优先级

一、前言 unix系统中&#xff0c;进程的调度是由内核决定的。在一个系统中&#xff0c;进程的优先级越高&#xff0c;表示其在一定时间中占用cpu的时间越久。本文将介绍unix系统如何修改以及获取进程的优先级。 二、nice值 nice值是unix系统中用于表征进程优先级的一个参数。…

MES系统中的正向追溯与反向追溯管理

随着制造业的日益发展&#xff0c;生产过程中的质量控制和管理变得尤为关键。MES系统作为一种实现车间生产管理和控制的重要工具&#xff0c;其追溯功能在生产过程中起着至关重要的作用。 一、MES系统概述 MES系统是一套面向制造企业车间执行层的生产信息化管理系统。它通过对…

药品名不得命名保健食品

益安宁丸为同溢堂药业有限公司所独家生产的一款中成药&#xff0c;在内地市场和港澳地区均有上市。

如何在算家云搭建MuseTalk(数字人)

一、 MuseTalk 简介 MuseTalk 是由腾讯团队开发的先进技术&#xff0c;它是一个实时的音频驱动唇部同步模型。该模型能够根据输入的音频信号&#xff0c;自动调整数字人物的面部图像&#xff0c;使其唇形与音频内容高度同步。 二、 MuseTalk 一键使用 基础环境最低要求说明&…

肺结节分割与提取系统(基于传统图像处理方法)

Matlab肺结节分割(肺结节提取)源程序&#xff0c;GUI人机界面版本。使用传统图像分割方法&#xff0c;非深度学习方法。使用LIDC-IDRI数据集。 工作如下&#xff1a; 1、读取图像。读取原始dicom格式的CT图像&#xff0c;并显示&#xff0c;绘制灰度直方图&#xff1b; 2、图像…

深圳市步步精科技有限公司荣获发明专利,彰显技术研发实力

2024年8月13日&#xff0c;深圳市步步精科技有限公司&#xff08;BBJconn&#xff09;正式获得了其新开发的防水连接器专利&#xff0c;授权公告号为CN 118352837 B。这项技术的突破标志着公司在连接器领域的持续创新&#xff0c;进一步巩固了其行业领先地位。 专利技术概述 此…

JavaScript 常用输出语句详解

目录 非 VIP 用户可前往公众号“前端基地”进行免费阅读 alert弹出警告框 Console 控制台输出 Document.write 直接在文档中显示 Prompt 弹出用户输入对话框 非 VIP 用户可前往公众号“前端基地”进行免费阅读 alert弹出警告框 在 JavaScript 中,alert可用于弹出…

Android Preference的使用以及解析

简单使用 values.arrays.xml <?xml version"1.0" encoding"utf-8"?> <resources><string-array name"list_entries"><item>Option 1</item><item>Option 2</item><item>Option 3</item&…

【权威出版|稳定检索】2024年信息学、网络与计算机应用技术国际会议(INCAT 2024)

2024 International Conference on Informatics, Networking, and Computer Application Technology 【1】大会信息 会议名称&#xff1a;2024年信息学、网络与计算机应用技术国际会议 会议简称&#xff1a;INCAT 2024 大会时间&#xff1a;请查看官网 大会地点&#xff1a;中…

携程酒店含价格全国城市分析1

在做一些城市分析、学术研究分析、商业选址、商业布局分析、住宿业分析等数据分析挖掘时&#xff0c;携程酒店的数据参考价值非常大&#xff0c;可以从酒店档次、分布、价格、特色服务等多维度来分析研究。 具体分析研究的字段维度包括酒店名、星级、星级类型、酒店标签、酒店…

通过GIS数据对比北京西城区和鹤岗工农区,数据解释为啥房价差异那么大

这两个区域都是所在城市的核心区域&#xff0c;而且北京西城区是老城区。面积不像其它区域那么大&#xff0c;所以对比起来有一定的代表性&#xff01;我从医疗机构和企业单位两方面进行了对比&#xff0c;他们分别可以代表我们的生活和就业&#xff01;当然我也想对学校教育对…

期权懂|期权中的看涨期权与看跌期权是什么意思?

本期让我懂 你就懂的期权懂带大家来了解&#xff0c;期权中的看涨期权与看跌期权是什么意思&#xff1f;有兴趣的朋友可以看一下。期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 期权中的看涨期权与看跌期权是什么意思&#xf…

sql-lab打不开网页了(没解决)

早上起来想打开sql-lab&#xff0c;发现变成这样了&#xff0c;昨天好像是因为aws&#xff0c;打开了一些服务&#xff0c;那我也没关闭一些服务吧.. 服务正常开启 也有mysql服务 尝试重启服务&#xff0c;发现问题&#xff0c;ok啊&#xff0c;还是很简单的&#xff0c;提示有…

Transformer宝藏入门教程,五天肝疯了—Transformer最全面的入门指南

前言 随着 BERT、GPT 等大规模语言模型的兴起&#xff0c;越来越多的公司和研究者采用 Transformers 库来构建 NLP 应用。本文档教程里包括了自然语言处理、Transformer模型、注意力机制、pytorch、微调预训练模型、翻译任务、序列标注任务、文本摘要等等模块 一、内容介绍 …

JVM篇(学习预热 - 云原生时代的JVM(GraalVM))(持续更新迭代)

目录 一、GraalVM是什么&#xff1f; 二、GraalVM有哪些特点&#xff1f; 1. 高性能 2. 多语言支持 3. 互操作性 4. 安全性 三、GraalVM的应用效果 1. 提高性能 2. 简化开发 3. 降低成本 4. 节省资源 5. 支持云环境 四、使用GraalVM编译springboot应用程序 1. 下载…

【JAVA面试题】Java和C++主要区别有哪些?各有哪些优缺点?

文章目录 强烈推荐前言区别&#xff1a;1. 语法和编程风格2.内存管理3.平台独立性4.性能5.指针和引用6.多线程7.使用场景 Java 的优缺点优点&#xff1a;缺点&#xff1a; C 的优缺点优点&#xff1a;缺点&#xff1a; 总结专栏集锦 强烈推荐 前些天发现了一个巨牛的人工智能学…

ARMv7/v8m GCC Compilation

00-Guide01-Toolchains02-GNU binutils03-ELF file04-Compilation process05-CFLAGS options06- Linker Scripts07 -Link Options08-Map file09-Static and dynamic lib10-Secureboot and image11-Builtin functions12-Function Attributes

Prometheus + Grafana 监控 MySQL 数据库

文章目录 1、前置介绍2、搭建流程2.1、安装 Docker2.2、安装 MySQL2.3、安装 MySQL Exporter2.4、安装 Prometheus2.5、安装 Grafana 1、前置介绍 本次监控平台搭建&#xff0c;我使用2台阿里云服务器来完成本次的搭建部署操作&#xff0c;配置如下&#xff1a; 阿里云ECS1&am…

重大更新,谷歌地球倾斜摄影数据OSGB转换软件V2.0版发布

距离谷歌倾斜摄影OSGB数据V1.2版发布已三月有余&#xff0c;这三个月除了忙于对转换软件进行Bug修复和数据效果提升外&#xff0c;最重要的是解决一个比较严重的问题&#xff0c;即倾斜摄影数据中除了倾斜摄影外&#xff0c;还包含没有倾斜摄影的影像数据。从软件V0.1版免费向大…

过于可爱!手把手教你用AI绘画工具SD做人气超高的毛绒玩具,SD毛绒玩具制作教程详解!

大家好&#xff0c;我是灵魂画师向阳 最近网上看到一些用 Stable Diffusion 生成的毛绒玩具&#xff0c;非常可爱。我也尝试了一下&#xff0c;效果很不错&#xff0c;还能体验一下自己做周边设计师的快乐。 这种效果做起来其实并不难&#xff0c;基本思路还是 controlnet 控…