【鸿蒙实战开发】模态转场、List 组件、AlphabetIndexer

打印 上一主题 下一主题

主题 981|帖子 981|积分 2943

一、模态转场

起首,先来讲一讲什么是模态转场吧,简朴来讲就是我们在手机上面看到的分享图标点击以后出来的一个半屏的分享界面,这个过程就叫做模态转场。
概念:就是从页面内弹出一个半屏大概全屏的一个弹框。

1.1、半模态转场

作用:就是给一个半屏的模态转场。

语法结构:
.bindSheet(iSshow/是否表现半模态页面,builder/配置半模态页面内容)
1.2、表现状态双向绑定

在非双向绑定环境下,以拖拽方式关闭半模态页面不会改变isShow参数的值。
为了使isShow参数值与半模态界面的状态同步,发起使用$$双向绑定isShow参数。

代码演示:
  1. @Entry
  2. @Component
  3. struct zy {
  4. @State isshow: boolean = false
  5. @Builder
  6. binBuilder() {
  7. Column() {
  8. Text('已打开')
  9. .fontSize(50)
  10. .fontColor(Color.Pink)
  11. }
  12. }
  13. build() {
  14. Column() {
  15. Text('打开半模态框')
  16. .fontSize(40)
  17. //点击后打开半模态框
  18. .onClick(() => {
  19. this.isshow = true
  20. })
  21. .bindSheet($this.isshow, //双向绑定半模态页面
  22. this.binBuilder()//模态框内的内容
  23. )
  24. }
  25. .width('100%')
  26. .height('100%')
  27. }
  28. }
复制代码
图片演示:

1.3、 可选属性sheetOptions

通过第三个可选参数SheetOptions,可以对半模态的内容举行调整
常用属性:

代码演示:
  1. @Entry
  2. @Component
  3. struct zy {
  4. @State isshow: boolean = false
  5. @Builder
  6. binBuilder() {
  7. Column() {
  8. Text('已打开')
  9. .fontSize(50)
  10. .fontColor(Color.Pink)
  11. //自定义的关闭模态框图标
  12. Text('x')
  13. .border({ width: 1, color: Color.Green })
  14. .height(30)
  15. .fontColor(Color.Gray)
  16. .fontSize(20)
  17. .position({ x: 210, y: 6 })
  18. .width(30)
  19. .textAlign(TextAlign.Center)
  20. .borderRadius(15)
  21. .onClick(() => {
  22. this.isshow = false
  23. })
  24. }
  25. }
  26. build() {
  27. Column() {
  28. Text('打开半模态框')
  29. .fontSize(40)//点击后打开半模态框
  30. .onClick(() => {
  31. this.isshow = true
  32. })
  33. .bindSheet($this.isshow, //双向绑定半模态页面
  34. this.binBuilder(), //模态框内的内容
  35. {
  36. height: 400, //模态框高度
  37. showClose: false, //关闭显示关闭图标,默认打开
  38. // detents:[100,200],//半模态页面的切换高度档位。
  39. dragBar: false//关闭控制条,默认显示
  40. })
  41. }
  42. .width('100%')
  43. .height('100%')
  44. }
  45. }
复制代码
效果图:

案例-分享弹框


代码演示:
  1. @Entry
  2. @Component
  3. struct zy {
  4. @State isshow: boolean = false
  5. //半模态框里面的内容
  6. @Builder
  7. bindBuilder() {
  8. Column({ space: 20 }) {
  9. Row() {
  10. Text('分享给好友')
  11. .fontColor('rgba(0,0,0,0.5)')
  12. .fontWeight(800)
  13. .fontSize(23)
  14. .textAlign(TextAlign.Center)
  15. .layoutWeight(1)
  16. Image($r('app.media.ic_public_cancel'))
  17. .width(30)
  18. .onClick(() => {
  19. this.isshow = false
  20. })
  21. }
  22. .padding(10)
  23. .width('100%')
  24. .justifyContent(FlexAlign.SpaceBetween)
  25. Row() {
  26. Column({ space: 5 }) {
  27. Image($r('app.media.ic_share_wechat'))
  28. .width(50)
  29. Text('微信')
  30. }
  31. Column({ space: 5 }) {
  32. Image($r('app.media.ic_share_pyq'))
  33. .width(50)
  34. Text('朋友圈')
  35. }
  36. Column({ space: 5 }) {
  37. Image($r('app.media.ic_share_sina'))
  38. .width(50)
  39. Text('微博')
  40. }
  41. Column({ space: 5 }) {
  42. Image($r('app.media.ic_share_url'))
  43. .width(50)
  44. Text('复制链接')
  45. }
  46. }
  47. .width('100%')
  48. .justifyContent(FlexAlign.SpaceAround)
  49. }
  50. .margin({ bottom: 50 })
  51. }
  52. build() {
  53. Column() {
  54. Button('转发')
  55. .onClick(() => {
  56. this.isshow = true
  57. })
  58. .bindSheet($this.isshow, this.bindBuilder(),
  59. {
  60. showClose: false, //关闭显示关闭图标
  61. height: SheetSize.FIT_CONTENT//高度自适应
  62. }
  63. )
  64. }
  65. .width('100%')
  66. .height('100%')
  67. }
  68. }
复制代码
效果图:

1.4、全屏模态

概念:顾名思义就是全屏的模态页面。

二、List组件

接着我们来讲一下今天List组件的小扩展,有些时候我们必要用List组件做一些相对有点复杂的效果,比如通讯录界面效果,那就必要ListItemGroup 分组容器和一些List组件的属性及事件来完成了。
2.1、分组展示

焦点用法:

  • List作为顶级容器
  • ListItemGroup 作为分组容器
  • ListItem作为 List 大概ListItemGroup的子组件

ListItemGroup组件参数,以对象形式传入

ListItemGroup(参数){}.属性()
参数:

属性:和List的属性是一样的

代码演示:
  1. @Entry
  2. @Component
  3. struct ListItemGroup_01 {
  4. @Builder
  5. headerBuilder() {
  6. Text('我是头部')
  7. }
  8. @Builder
  9. footerBuilder() {
  10. Text('我是底部')
  11. }
  12. build() {
  13. List() {
  14. ListItemGroup({
  15. header: this.headerBuilder(),
  16. footer: this.footerBuilder(),
  17. space: 20
  18. }) {
  19. ListItem() {
  20. Text('我是内容')
  21. .backgroundColor(Color.Orange)
  22. }
  23. ListItem() {
  24. Text('我是内容')
  25. .backgroundColor(Color.Orange)
  26. }
  27. }
  28. .divider({ strokeWidth: 1, color: Color.Orange,startMargin:40 })
  29. }
  30. }
  31. }
复制代码
效果图:

小案例


代码演示:
  1. @Entry
  2. @Component
  3. struct ContactsList {
  4. build() {
  5. List() {
  6. //头部参数A
  7. ListItemGroup({ header: this.itemHead('A'), space: 20 }) {
  8. // 循环渲染分组A的ListItem
  9. this.contactBuilder('艾佳')
  10. this.contactBuilder('安安')
  11. this.contactBuilder('艾米丽')
  12. }
  13. //分割线
  14. .divider({
  15. startMargin: 60,
  16. strokeWidth: 1,
  17. color: '#ccc'
  18. })
  19. //头部参数B
  20. ListItemGroup({ header: this.itemHead('B'), space: 20 }) {
  21. // 循环渲染分组B的ListItem
  22. this.contactBuilder('白客')
  23. this.contactBuilder('白夜')
  24. this.contactBuilder('博明')
  25. }
  26. .divider({
  27. startMargin: 60,
  28. strokeWidth: 1,
  29. color: '#ccc'
  30. })
  31. }
  32. }
  33. @Builder
  34. itemHead(text: string) {
  35. // 列表分组的头部组件,对应联系人分组A、B等位置的组件
  36. Text(text)
  37. .fontSize(20)
  38. .backgroundColor('#fff1f3f5')
  39. .width('100%')
  40. .padding(5)
  41. }
  42. @Builder
  43. contactBuilder(name: string) {
  44. //列表分组的内容组件
  45. ListItem() {
  46. Row({ space: 10 }) {
  47. Image($r('app.media.ic_public_lianxiren'))
  48. .width(40)
  49. .fillColor('#e4b99a')
  50. Text(name)
  51. }
  52. }
  53. }
  54. }
复制代码
效果图片:

2.2、粘性标题

作用:
配合ListItemGroup组件使用,设置ListItemGroup中header和footer是否要吸顶或吸底。

代码演示:
  1. List(){
  2. }
  3. // .sticky(StickyStyle.None) // 不吸附 默认值
  4. // .sticky(StickyStyle.Header) // 头部吸附
  5. // .sticky(StickyStyle. Footer) //  底部吸附,如果有的话
复制代码
2.3、控制滚动

作用:如果列表很长,必要快速滚动到列表底部或返回列表顶部,就可以使用代码来控制滚动。
关键步骤:

  • 创建控制器(ListScroller)对象
  • 设置给 List 组件
  • 调用控制器对象的方法,实现滚动
代码演示:
  1. // 1\. 创建控制器(ListScroller)对象
  2. listScroller: ListScroller = new ListScroller()
  3. // 2\. 设置给 List 组件
  4. List({ space: 20, scroller: this.listScroller }) {
  5. // ...
  6. }
  7. Button() {
  8. // ...
  9. }
  10. .onClick(() => {
  11. // 3\. 调用控制器对象的方法,实现滚动
  12. this.listScroller.scrollToIndex(0)
  13. })
复制代码
参数:

2.4、事件


案例(通讯录)

需求1:数据渲染
数据2:设置随机头像颜色
需求3:头部粘性标题
需求4:通过控制滚动点击通讯录回到顶部
代码演示:
  1. interface ContactContent {
  2. initial: string
  3. nameList: string[]
  4. }
  5. @Entry
  6. @Component
  7. struct ContactsList {
  8. contacts: ContactContent[] = [
  9. { initial: 'A', nameList: ['阿猫', '阿狗', '阿虎', '阿龙', '阿鹰', '阿狼', '阿豹', '阿狮', '阿象', '阿鲸'] },
  10. { initial: 'B', nameList: ['白兔', '白鸽', '白鹤', '白鹭', '白狐', '白狼', '白虎', '白鹿', '白蛇', '白马'] },
  11. { initial: 'C', nameList: ['春花', '春风', '春雨', '春草', '春柳', '春燕', '春莺', '春蝶', '春蓝', '春绿'] },
  12. { initial: 'D', nameList: ['冬雪', '冬梅', '冬松', '冬竹', '冬云', '冬霜', '冬月', '冬夜', '冬青', '冬红'] },
  13. { initial: 'E', nameList: ['饿狼', '饿虎', '饿鹰', '饿豹', '饿熊', '饿蛇', '饿鱼', '饿虾', '饿蟹', '饿蚌'] },
  14. { initial: 'F', nameList: ['飞鸟', '飞鱼', '飞虫', '飞蜂', '飞蝶', '飞蛾', '飞蝉', '飞蝗', '飞鼠', '飞猫'] },
  15. { initial: 'G', nameList: ['孤狼', '孤鹰', '孤虎', '孤豹', '孤蛇', '孤鲨', '孤鲸', '孤鹿', '孤雁', '孤鸿'] },
  16. { initial: 'H', nameList: ['海鸥', '海龟', '海豚', '海星', '海马', '海葵', '海参', '海胆', '海螺', '海贝'] },
  17. { initial: 'I', nameList: ['火焰', '火球', '火箭', '火山', '火车', '火柴', '火把', '火鸟'] },
  18. { initial: 'J', nameList: ['金鱼', '金狮', '金刚', '金鹿', '金蛇', '金鹰', '金豹', '金虎', '金狐', '金猫'] },
  19. { initial: 'K', nameList: ['孔雀', '恐龙', '开心', '开怀', '开朗', '开拓', '开口', '开花', '开眼', '开天'] },
  20. { initial: 'L', nameList: ['老虎', '老鹰', '老鼠', '老狼', '老狗', '老猫', '老熊', '老鹿', '老龟', '老蛇'] },
  21. { initial: 'M', nameList: ['玫瑰', '牡丹', '梅花', '茉莉', '木兰', '棉花', '蜜蜂', '蚂蚁', '马蜂', '蟒蛇'] },
  22. { initial: 'N', nameList: ['南山', '南极', '南海', '南京', '南阳', '南风', '南瓜', '南竹', '南花', '南鸟'] },
  23. {
  24. initial: 'O',
  25. nameList: ['熊猫', '欧鹭', '欧洲', '欧阳', '欧文', '欧若拉', '欧米茄', '欧罗巴', '欧菲莉亚', '欧瑞斯']
  26. },
  27. { initial: 'P', nameList: ['苹果', '葡萄', '琵琶', '枇杷', '菩提', '瓢虫', '瓢泼', '飘零', '飘渺', '飘飘然'] },
  28. { initial: 'Q', nameList: ['七喜', '强风', '奇迹', '乾坤', '奇才', '晴天', '青竹', '秋水', '轻舞', '清泉'] },
  29. { initial: 'R', nameList: ['瑞雪', '瑞兽', '瑞光', '瑞云', '瑞彩', '瑞气', '瑞香', '瑞草', '瑞莲', '瑞竹'] },
  30. { initial: 'S', nameList: ['三羊', '三狗', '三猫', '三鱼', '三角', '三鹿', '三鹰', '三蛇', '三狐', '三豹'] },
  31. { initial: 'T', nameList: ['太阳', '天空', '田园', '太极', '太湖', '天鹅', '太空', '天使', '坦克', '甜橙'] },
  32. { initial: 'U', nameList: ['乌鸦', '乌鹊', '乌鱼', '乌龟', '乌云', '乌梅', '乌木', '乌金', '乌黑', '乌青'] },
  33. { initial: 'V', nameList: ['五虎', '五狼', '五鹰', '五豹', '五熊', '五蛇', '五鲨', '五鲸', '五鹿', '五马'] },
  34. { initial: 'W', nameList: ['悟空', '微笑', '温暖', '无畏', '温柔', '舞蹈', '问心', '悟道', '未来', '文学'] },
  35. { initial: 'X', nameList: ['西风', '西洋', '西子', '西施', '西岳', '西湖', '西柚', '西竹', '西花', '西鸟'] },
  36. { initial: 'Y', nameList: ['夜猫', '夜鹰', '夜莺', '夜空', '夜色', '夜月', '夜影', '夜翼', '夜狐', '夜狼'] },
  37. { initial: 'Z', nameList: ['珍珠', '紫薇', '紫霞', '紫竹', '紫云', '紫燕', '紫鸢', '紫藤', '紫荆', '紫罗兰'] },
  38. ]
  39. //创建控制器(ListScroller)对象
  40. ls: ListScroller = new ListScroller()
  41. //随机颜色
  42. getRandomColor(): ResourceColor {
  43. const r = Math.floor(Math.random() * 256);
  44. const g = Math.floor(Math.random() * 256);
  45. const b = Math.floor(Math.random() * 256);
  46. return `rgba(${r}, ${g}, ${b}, 0.5)`;
  47. }
  48. build() {
  49. Column() {
  50. Stack({ alignContent: Alignment.End }) {
  51. Text('通讯录')
  52. .width('100%')
  53. .textAlign(TextAlign.Center)
  54. .fontSize(20)
  55. //调用控制器对象的方法,实现滚动
  56. .onClick(() => {
  57. this.ls.scrollToIndex(0, true, ScrollAlign.START)
  58. })
  59. Image($r('app.media.ic_public_add'))
  60. .width(20)
  61. }
  62. .width('100%')
  63. .padding(15)
  64. .backgroundColor('#fff1f3f5')
  65. //绑定List 组件
  66. List({ scroller: this.ls }) {
  67. // 顶部
  68. ListItem() {
  69. Row() {
  70. Image($r('app.media.ic_public_search'))
  71. .width(20)
  72. .fillColor(Color.Gray)
  73. Text('搜索')
  74. .fontColor(Color.Gray)
  75. }
  76. .backgroundColor(Color.White)
  77. .width('100%')
  78. .height(40)
  79. .borderRadius(5)
  80. .justifyContent(FlexAlign.Center)
  81. }
  82. .padding(10)
  83. .width('100%')
  84. .backgroundColor('#fff1f3f5')
  85. //循环渲染对象数组
  86. ForEach(this.contacts, (item: ContactContent) => {
  87. ListItemGroup({ header: this.itemHead(item.initial), space: 10 }) {
  88. // 循环渲染分组A的ListItem
  89. ForEach(item.nameList, (name: string) => {
  90. this.contactBuilder(name, this.getRandomColor())
  91. })
  92. }
  93. .divider({
  94. startMargin: 60,
  95. strokeWidth: 1,
  96. color: '#ccc'
  97. })
  98. })
  99. }
  100. .sticky(StickyStyle.Header)//头部粘性标题
  101. }
  102. }
  103. @Builder
  104. itemHead(text: string) {
  105. // 列表分组的头部组件,对应联系人分组A、B等位置的组件
  106. Text(text)
  107. .fontSize(20)
  108. .backgroundColor('#fff1f3f5')
  109. .width('100%')
  110. .padding(5)
  111. }
  112. @Builder
  113. contactBuilder(name: string, color: ResourceColor) {
  114. ListItem() {
  115. Row({ space: 10 }) {
  116. Image($r('app.media.ic_public_lianxiren'))
  117. .width(40)
  118. .fillColor(color)
  119. Text(name)
  120. }
  121. }
  122. }
  123. }
复制代码
效果图:

三、AlphabetIndexer组件

作用:通过 AlphabetIndexer 组件可以与容器组件结合,实现导航联动,以及快速定位的效果。
3.1、焦点用法

AlphabetIndexer不是容器组件,属于功能类的组件,使用时,必要设置如下 2 个参数。

通过双向绑定变量。可以实现修改变量值,同步更新选中的索引
代码演示:
  1. @Entry
  2. @Component
  3. struct ContactsList {
  4. @State selectedIndex:number = 0
  5. alphabets: string[] = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  6. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
  7. build() {
  8. Stack({ alignContent: Alignment.End }) {
  9. // 字母表索引组件
  10. AlphabetIndexer({ arrayValue: this.alphabets, selected: $this.selectedIndex })
  11. }
  12. .width('100%')
  13. .height('100%')
  14. }
  15. }
复制代码
3.2、外观设置

设置文字外观

如果默认的颜色效果无法满意要求,可以通过如下属性来举行设置。

代码演示:
  1. .color(Color.Orange)// 文字颜色
  2. .selectedColor(Color.Green)// 选中文字颜色
  3. .selectedBackgroundColor(Color.Black) // 选中背景颜色
复制代码
弹窗提示

如果默认的文字高亮效果无法满意要求,还可以通过弹框来表现,对应属性如下:

  1. .usingPopup(true)//使用弹窗
  2. .popupColor(Color.Orange)// 弹窗文字颜色
  3. .popupTitleBackground(Color.Pink)  // 弹窗背景颜色
复制代码
3.3、事件

代码演示:
  1. @Entry
  2. @Component
  3. struct ContactsList {
  4. @State selectedIndex: number = 0;
  5. alphabets: string[] = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  6. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
  7. build() {
  8. Stack({ alignContent: Alignment.End }) {
  9. Text(this.selectedIndex + '')
  10. .width('100%')
  11. // 字母表索引组件
  12. AlphabetIndexer({ arrayValue: this.alphabets, selected: this.selectedIndex })
  13. .usingPopup(true)
  14. .onSelect((index: number) => {
  15. this.selectedIndex = index
  16. })
  17. }
  18. .width('100%')
  19. .height('100%')
  20. }
  21. }
复制代码
综合案例(通讯录)

结合AlphabetIndexer组件,让字母索引与通讯录索引联动
代码演示:
  1. interface ContactContent {
  2. initial: string
  3. nameList: string[]
  4. }
  5. @Entry
  6. @Component
  7. struct ContactsList {
  8. contacts: ContactContent[] = [
  9. { initial: 'A', nameList: ['阿猫', '阿狗', '阿虎', '阿龙', '阿鹰', '阿狼', '阿豹', '阿狮', '阿象', '阿鲸'] },
  10. { initial: 'B', nameList: ['白兔', '白鸽', '白鹤', '白鹭', '白狐', '白狼', '白虎', '白鹿', '白蛇', '白马'] },
  11. { initial: 'C', nameList: ['春花', '春风', '春雨', '春草', '春柳', '春燕', '春莺', '春蝶', '春蓝', '春绿'] },
  12. { initial: 'D', nameList: ['冬雪', '冬梅', '冬松', '冬竹', '冬云', '冬霜', '冬月', '冬夜', '冬青', '冬红'] },
  13. { initial: 'E', nameList: ['饿狼', '饿虎', '饿鹰', '饿豹', '饿熊', '饿蛇', '饿鱼', '饿虾', '饿蟹', '饿蚌'] },
  14. { initial: 'F', nameList: ['飞鸟', '飞鱼', '飞虫', '飞蜂', '飞蝶', '飞蛾', '飞蝉', '飞蝗', '飞鼠', '飞猫'] },
  15. { initial: 'G', nameList: ['孤狼', '孤鹰', '孤虎', '孤豹', '孤蛇', '孤鲨', '孤鲸', '孤鹿', '孤雁', '孤鸿'] },
  16. { initial: 'H', nameList: ['海鸥', '海龟', '海豚', '海星', '海马', '海葵', '海参', '海胆', '海螺', '海贝'] },
  17. { initial: 'I', nameList: ['火焰', '火球', '火箭', '火山', '火车', '火柴', '火把', '火鸟'] },
  18. { initial: 'J', nameList: ['金鱼', '金狮', '金刚', '金鹿', '金蛇', '金鹰', '金豹', '金虎', '金狐', '金猫'] },
  19. { initial: 'K', nameList: ['孔雀', '恐龙', '开心', '开怀', '开朗', '开拓', '开口', '开花', '开眼', '开天'] },
  20. { initial: 'L', nameList: ['老虎', '老鹰', '老鼠', '老狼', '老狗', '老猫', '老熊', '老鹿', '老龟', '老蛇'] },
  21. { initial: 'M', nameList: ['玫瑰', '牡丹', '梅花', '茉莉', '木兰', '棉花', '蜜蜂', '蚂蚁', '马蜂', '蟒蛇'] },
  22. { initial: 'N', nameList: ['南山', '南极', '南海', '南京', '南阳', '南风', '南瓜', '南竹', '南花', '南鸟'] },
  23. {
  24. initial: 'O',
  25. nameList: ['熊猫', '欧鹭', '欧洲', '欧阳', '欧文', '欧若拉', '欧米茄', '欧罗巴', '欧菲莉亚', '欧瑞斯']
  26. },
  27. { initial: 'P', nameList: ['苹果', '葡萄', '琵琶', '枇杷', '菩提', '瓢虫', '瓢泼', '飘零', '飘渺', '飘飘然'] },
  28. { initial: 'Q', nameList: ['七喜', '强风', '奇迹', '乾坤', '奇才', '晴天', '青竹', '秋水', '轻舞', '清泉'] },
  29. { initial: 'R', nameList: ['瑞雪', '瑞兽', '瑞光', '瑞云', '瑞彩', '瑞气', '瑞香', '瑞草', '瑞莲', '瑞竹'] },
  30. { initial: 'S', nameList: ['三羊', '三狗', '三猫', '三鱼', '三角', '三鹿', '三鹰', '三蛇', '三狐', '三豹'] },
  31. { initial: 'T', nameList: ['太阳', '天空', '田园', '太极', '太湖', '天鹅', '太空', '天使', '坦克', '甜橙'] },
  32. { initial: 'U', nameList: ['乌鸦', '乌鹊', '乌鱼', '乌龟', '乌云', '乌梅', '乌木', '乌金', '乌黑', '乌青'] },
  33. { initial: 'V', nameList: ['五虎', '五狼', '五鹰', '五豹', '五熊', '五蛇', '五鲨', '五鲸', '五鹿', '五马'] },
  34. { initial: 'W', nameList: ['悟空', '微笑', '温暖', '无畏', '温柔', '舞蹈', '问心', '悟道', '未来', '文学'] },
  35. { initial: 'X', nameList: ['西风', '西洋', '西子', '西施', '西岳', '西湖', '西柚', '西竹', '西花', '西鸟'] },
  36. { initial: 'Y', nameList: ['夜猫', '夜鹰', '夜莺', '夜空', '夜色', '夜月', '夜影', '夜翼', '夜狐', '夜狼'] },
  37. { initial: 'Z', nameList: ['珍珠', '紫薇', '紫霞', '紫竹', '紫云', '紫燕', '紫鸢', '紫藤', '紫荆', '紫罗兰'] },
  38. ]
  39. //取0-255的随机数来通过rgba做随机颜色
  40. colors() {
  41. let r = Math.floor(Math.random() * 256)
  42. let g = Math.floor(Math.random() * 256)
  43. let b = Math.floor(Math.random() * 256)
  44. return `rgba(${r},${g},${b},0.5)`
  45. }
  46. i: ListScroller = new ListScroller()
  47. @State index1: number = 0
  48. alphabets: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  49. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
  50. build() {
  51. Column() {
  52. Stack({ alignContent: Alignment.End }) {
  53. Text('通讯录')
  54. .width('100%')
  55. .textAlign(TextAlign.Center)
  56. .fontSize(20)
  57. Image($r('app.media.ic_public_add'))
  58. .width(20)
  59. }
  60. .width('100%')
  61. .padding(15)
  62. .backgroundColor('#fff1f3f5')
  63. // 顶部
  64. Row() {
  65. Image($r('app.media.ic_public_search'))
  66. .width(20)
  67. .fillColor(Color.Gray)
  68. Text('搜索')
  69. .fontColor(Color.Gray)
  70. }
  71. .backgroundColor(Color.White)
  72. .width('100%')
  73. .height(40)
  74. .borderRadius(5)
  75. .justifyContent(FlexAlign.Center)
  76. Stack({ alignContent: Alignment.End }) {
  77. List({ scroller: this.i }) {
  78. ForEach(this.contacts, (item: ContactContent) => {
  79. ListItemGroup({ header: this.itemHead(item.initial), space: 10 }) {
  80. // 循环渲染分组A的ListItem
  81. ForEach(item.nameList, (name: string) => {
  82. this.contactBuilder(name, this.colors())
  83. })
  84. }
  85. .divider({
  86. startMargin: 60,
  87. strokeWidth: 1,
  88. color: '#ccc'
  89. })
  90. })
  91. }
  92. .sticky(StickyStyle.Header)
  93. .onScrollIndex((index: number) => {
  94. console.log(index.toString())
  95. this.index1 = index
  96. })
  97. .scrollBar(BarState.Off)
  98. AlphabetIndexer({ arrayValue: this.alphabets, selected: this.index1 })
  99. .onSelect((index: number) => {
  100. this.i.scrollToIndex(index)
  101. })
  102. .usingPopup(true)
  103. .itemSize(22)
  104. .popupColor(Color.Pink)
  105. .popupPosition({ x: 20, y: 0 })
  106. }
  107. }
  108. }
  109. @Builder
  110. itemHead(text: string) {
  111. // 列表分组的头部组件,对应联系人分组A、B等位置的组件
  112. Text(text)
  113. .fontSize(20)
  114. .backgroundColor('#fff1f3f5')
  115. .width('100%')
  116. .padding(5)
  117. }
  118. @Builder
  119. contactBuilder(name: string, color: ResourceColor) {
  120. ListItem() {
  121. Row({ space: 10 }) {
  122. Image($r('app.media.ic_public_lianxiren'))
  123. .width(40)
  124. .fillColor(color)
  125. Text(name)
  126. }
  127. }
  128. }
  129. }
复制代码
写在最后

●如果你觉得这篇内容对你还蛮有资助,我想邀请你帮我两个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以等待后续文章ing

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

渣渣兔

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表