先看效果
直入主题
UI结构
Stack帧结构容器+List联系人列表+AlphabetIndexer字母索引器
实现代码
1. 先定义好假数据
- 通讯录列表数据
private dataList: any = [
{
title: '',
contactList: [
{ name: "新的朋友", head: $r("app.media.ic_new_friend") },
{ name: "群聊", head: $r("app.media.ic_group_chat") },
{ name: "标签", head: $r("app.media.ic_tag") },
{ name: "公众号", head: $r("app.media.ic_official_account") }
]
},
{
title: 'A',
contactList: [
{ name: "ArdWard", head: $r("app.media.ic_user_head2") },
{ name: "阿联酋", head: $r("app.media.ic_user_head3") },
{ name: "艾森宝", head: $r("app.media.ic_user_head6") }
]
},
.....忽略中间数据
{
title: 'Z',
contactList: [
{ name: "猪八戒", head: $r("app.media.ic_user_head3") },
{ name: "张宇恒", head: $r("app.media.ic_user_head4") },
{ name: "周大年", head: $r("app.media.ic_user_head5") }
]
}
]
- 字母索引器列表数据
private letterList: string[] = ['↑', '☆', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#']
2. 再进行UI开发
从上文dataList
数据结构里可以看出,我做了List嵌套List结构方式以适用通讯录中大组标签(A,B,C...)和它们各自的联系人列表,好在鸿蒙原生组件也支持了这样的列表模式:
List(整体列表) --> ListItemGroup(A,B,C...组标签) ---> ListItem(联系人列表)
- 那么直接代码实现列表:
build() {
Stack({ alignContent: Alignment.End }) {
Column() {
// 标题栏
WechatToolbar({ title: "通讯录" })
// 通讯录列表
List({ scroller: this.scroller }) {
// 遍历循环大组标签
ForEach(this.dataList, (item) => {
// 大组标签
ListItemGroup({ header: this.itemHead(item.title) }) {
// 遍历循环大组内的联系人列表
ForEach(item.contactList, (contact) => {
// 小组联系人列表
ListItem() {
ListContactItem({ head: contact.head, name: contact.name })
}
.onClick(()=>{
router.pushUrl({ url: 'pages/chat/ChatPage',
params: { name: contact.name}
})
})
})
}
.divider({ strokeWidth: 0.8, color: '#f0f0f0', startMargin: 85, endMargin: 0 }) // 每行之间的分界线
})
}
.width('100%')
.height(0)
.layoutWeight(1)
.backgroundColor(Color.White)
}
.width("100%")
.height("100%")
...... 忽略部分代码
}.width("100%")
.height("100%")
}
@Builder itemHead(title: string) {
Text(title)
.fontSize(14)
.visibility("" === title ? Visibility.None : Visibility.Visible)
.backgroundColor("#EDEDED")
.height(36)
.width("100%")
.padding({ left: 20 })
}
- 字母索引器也有原生组件支持,直接看实现代码:
AlphabetIndexer({ arrayValue: this.letterList, selected: 0 })
.color(Color.Black)
.font({ size: 14 })
.selectedFont({ size: 14 })
.selectedColor(Color.Black)
.selectedBackgroundColor(Color.Transparent)
.usingPopup(true)
.popupColor(Color.White)
.popupBackground("#57be6a")
.popupFont({ size: 32, weight: FontWeight.Bolder })
.itemSize(20)
.alignStyle(IndexerAlign.Right)
.margin({ top: 80 })
.onSelect((index: number) => {
let letter = this.letterList[index]
var target: number = 0
for (const item of this.dataList) {
if (letter === item.title) {
this.scroller.scrollToIndex(target)
prompt.showToast({ message: "" + target })
break
}
target++
}
})
关键点在于AlphabetIndexer
的onSelect
事件中利用List
的scroller
进行滚动锚定,即:点击索引器的任意字母,联系人列表会自动跟着同步滚动。
最后贴下联系人自定义组件代码:
@Preview
@Component
export default struct ListContactItem {
private head: string | PixelMap | Resource
private name: string
build() {
Row() {
Image(this.head)
.width(46)
.height(46)
.borderRadius(4)
.margin({ left: 20, right: 15 })
.objectFit(ImageFit.Cover)
Text(this.name)
.fontSize(19)
.fontWeight(500)
.width("100%")
.layoutWeight(1)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ right: 30 })
.fontColor(Color.Black)
}
.backgroundColor(Color.White)
.width("100%")
.height(60)
}
}
最后大功告成,需要完整源码的童鞋可跟进《鸿蒙(HarmonyOS)ArkTs版微信APP》文章获取。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容