143.[HarmonyOS NEXT 实战案例十:List系列] 字母索引列表组件实战:打造高效联系人应用 基础篇

2025-06-30 22:18:22
104次阅读
0个评论

[HarmonyOS NEXT 实战案例十:List系列] 字母索引列表组件实战:打造高效联系人应用 基础篇

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

效果演示

image.png

一、字母索引列表基础介绍

在HarmonyOS NEXT应用开发中,字母索引列表是一种常见的UI模式,特别适合展示按字母分类的数据,如联系人、城市列表等。通过结合ListItemGroup和AlphabetIndexer组件,我们可以创建一个既美观又高效的字母索引列表,提升用户查找体验。

1.1 字母索引列表的组成部分

组成部分 说明
List 基础列表容器,用于展示所有内容
ListItemGroup 分组组件,用于按字母分组显示列表项
AlphabetIndexer 字母索引器,显示在列表侧边,用于快速导航到对应字母分组
Scroller 滚动控制器,用于控制列表滚动到指定位置

1.2 相关组件介绍

1.2.1 AlphabetIndexer组件

AlphabetIndexer是HarmonyOS NEXT提供的字母索引器组件,用于在列表旁边显示字母索引,支持用户通过点击或滑动快速定位到对应的列表位置。

主要属性 类型 说明
arrayValue string[] 索引器中显示的字符数组
selected number 当前选中项的索引
color ResourceColor 索引器的颜色
selectedColor ResourceColor 选中项的颜色
popupColor ResourceColor 弹出提示的颜色
selectedBackgroundColor ResourceColor 选中项的背景颜色
itemSize number 索引项的大小
font Font 索引项的字体样式
selectedFont Font 选中项的字体样式
popupFont Font 弹出提示的字体样式
usingPopup boolean 是否使用弹出提示
alignStyle IndexerAlign 索引器的对齐方式

1.2.2 Scroller控制器

Scroller是HarmonyOS NEXT提供的滚动控制器,用于控制可滚动组件(如List)的滚动行为。

主要方法 说明
scrollTo 滚动到指定位置
scrollToIndex 滚动到指定索引的项
scrollEdge 滚动到边缘
scrollPage 滚动一页

二、字母索引列表实战案例

2.1 需求分析

我们将实现一个按字母分组的联系人列表,包含以下功能:

  1. 联系人按首字母分组显示
  2. 每个分组有明显的标题
  3. 右侧显示字母索引器,支持快速导航
  4. 点击字母索引时,列表自动滚动到对应分组
  5. 列表滚动时,字母索引器同步更新选中状态

2.2 数据模型定义

首先,我们定义联系人和分组的数据模型:

interface ContactType {
    name: string,
    phone: string,
    avatar?: Resource
}

interface AlphabetIndexerType {
    key: string,
    contacts: ContactType[]
}

然后,准备按字母分组的联系人数据:

private contactGroups:AlphabetIndexerType[] = [
    {
        key: 'A',
        contacts: [
            { name: '艾伦', phone: '138-0000-0001', avatar: $r('app.media.big27') },
            { name: '安妮', phone: '138-0000-0002', avatar: $r('app.media.big26') },
            { name: '奥利弗', phone: '138-0000-0003', avatar: $r('app.media.big25') }
        ]
    },
    {
        key: 'B',
        contacts: [
            { name: '白露', phone: '138-0000-0004', avatar: $r('app.media.big24') },
            { name: '鲍勃', phone: '138-0000-0005', avatar: $r('app.media.big23') },
            { name: '贝蒂', phone: '138-0000-0006', avatar: $r('app.media.big22') }
        ]
    },
    // 其他字母分组...
]

2.3 获取索引字母数组

我们需要从联系人分组数据中提取所有的索引字母,用于AlphabetIndexer组件:

private get indexLetters(): string[] {
    return this.contactGroups.map(group => group.key)
}

2.4 分组头部实现

接下来,我们实现分组的头部,显示字母标题:

@Builder
GroupHeader(key: string) {
    Text(key)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .backgroundColor('#F1F3F5')
        .width('100%')
        .padding({ left: 16, top: 8, bottom: 8 })
}

2.5 页面结构设计

整个页面采用Stack布局,包含主要内容和字母索引器两部分:

build() {
    Stack({ alignContent: Alignment.TopEnd }) {
        // 主要内容
        Column() {
            // 标题栏
            Row() {
                // 标题栏内容
            }
            
            // 联系人列表
            List() {
                // 列表内容
            }
        }
        
        // 字母索引器
        AlphabetIndexer() {
            // 索引器配置
        }
    }
}

2.6 标题栏实现

标题栏包含标题文本和操作按钮:

Row() {
    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 })
}
.width('100%')
.height(56)
.padding({ left: 16 })
.backgroundColor('#F1F3F5')

2.7 联系人列表实现

联系人列表使用List和ListItemGroup组件,按字母分组显示联系人:

private scroller: Scroller = new Scroller() // 滚动控制器
@State currentIndex: number = 0 // 当前索引

// 联系人列表
List({ scroller: this.scroller }) {
    ForEach(this.contactGroups, (group:AlphabetIndexerType, groupIndex) => {
        ListItemGroup({
            header: this.GroupHeader(group.key),
            space: 0
        }) {
            ForEach(group.contacts, (contact:ContactType) => {
                ListItem() {
                    Row() {
                        // 头像
                        Image(contact.avatar || $r('app.media.big1'))
                            .width(40)
                            .height(40)
                            .borderRadius(20)
                            .margin({ right: 16 })

                        // 联系人信息
                        Column() {
                            Text(contact.name)
                                .fontSize(16)
                                .fontWeight(FontWeight.Medium)
                            Text(contact.phone)
                                .fontSize(14)
                                .fontColor('#666666')
                                .margin({ top: 4 })
                        }
                        .alignItems(HorizontalAlign.Start)
                    }
                    .width('100%')
                    .padding({ left: 16, right: 16, top: 12, bottom: 12 })
                }
                .height(64)
            })
        }
    })
}
.width('100%')
.layoutWeight(1)
.onScrollIndex((firstIndex: number) => {
    // 更新当前索引
    this.currentIndex = firstIndex
})
.divider({ // 设置分割线
    strokeWidth: 1,
    color: '#E5E5E5',
    startMargin: 72,
    endMargin: 16
})

2.8 字母索引器实现

最后,我们实现字母索引器,并处理索引选择事件:

AlphabetIndexer({
    arrayValue: this.indexLetters,
    selected: this.currentIndex
})
    .itemSize(16) // 字母大小
    .font({ size: 14 }) // 字体大小
    .selectedFont({ size: 16, weight: FontWeight.Bold }) // 选中字体样式
    .popupFont({ size: 30, weight: FontWeight.Bold }) // 弹出字体样式
    .selectedBackgroundColor('#007DFF') // 选中背景色
    .popupColor('#CCCCCC') // 弹出颜色
    .usingPopup(true) // 使用弹出效果
    .alignStyle(IndexerAlign.Right) // 右侧对齐
    .margin({ right: 8 })
    .onSelect((index: number) => {
        // 滚动到对应索引位置
        this.currentIndex = index
        this.scroller.scrollToIndex(index)
    })

三、完整代码解析

@Component
export struct AlphabetIndexerList {
    private scroller: Scroller = new Scroller() // 滚动控制器
    @State currentIndex: number = 0 // 当前索引

    // 按字母分组的联系人数据
    private contactGroups:AlphabetIndexerType[] = [
        // 数据定义(同上)
    ]

    // 获取所有索引字母
    private get indexLetters(): string[] {
        return this.contactGroups.map(group => group.key)
    }

    // 构建分组头部
    @Builder
    GroupHeader(key: string) {
        // 头部实现(同上)
    }

    build() {
        Stack({ alignContent: Alignment.TopEnd }) {
            Column() {
                // 标题栏
                Row() {
                    // 标题栏实现(同上)
                }

                // 联系人列表
                List({ scroller: this.scroller }) {
                    // 列表实现(同上)
                }
            }
            .width('100%')
            .height('100%')

            // 字母索引器
            AlphabetIndexer({
                // 索引器实现(同上)
            })
        }
        .width('100%')
        .height('100%')
        .backgroundColor('#FFFFFF')
    }
}

3.1 代码结构分析

部分 说明
数据模型 定义ContactType和AlphabetIndexerType接口,描述联系人和分组的数据结构
数据准备 创建contactGroups数组,包含按字母分组的联系人数据
索引字母 通过indexLetters计算属性获取所有索引字母
构建器 定义GroupHeader构建器,用于创建分组的头部
页面结构 使用Stack作为根容器,包含主要内容和字母索引器
联系人列表 使用List和ListItemGroup创建分组列表,每个分组包含多个ListItem
字母索引器 使用AlphabetIndexer创建字母索引器,处理索引选择事件

3.2 关键技术点分析

3.2.1 List与Scroller的结合使用

通过将Scroller实例传递给List组件,我们可以在外部控制列表的滚动行为:

private scroller: Scroller = new Scroller()

List({ scroller: this.scroller }) {
    // 列表内容
}

3.2.2 onScrollIndex事件处理

通过监听List的onScrollIndex事件,我们可以获取当前显示的第一个项的索引,用于更新字母索引器的选中状态:

.onScrollIndex((firstIndex: number) => {
    this.currentIndex = firstIndex
})

3.2.3 AlphabetIndexer与List的联动

通过AlphabetIndexer的onSelect事件和Scroller的scrollToIndex方法,我们实现了字母索引器与列表的联动:

.onSelect((index: number) => {
    this.currentIndex = index
    this.scroller.scrollToIndex(index)
})

3.2.4 Stack布局的使用

使用Stack布局可以将字母索引器叠加在主要内容上,并通过alignContent属性控制其位置:

Stack({ alignContent: Alignment.TopEnd }) {
    // 主要内容
    // 字母索引器
}

总结

在本篇教程中,我们学习了如何使用HarmonyOS NEXT的ListItemGroup和AlphabetIndexer组件创建一个字母索引列表。我们从数据模型定义、分组头部实现、页面结构设计到联系人列表和字母索引器实现,全面讲解了字母索引列表的实现过程。

收藏00

登录 后评论。没有帐号? 注册 一个。

全栈若城

  • 0回答
  • 4粉丝
  • 0关注
相关话题