鸿蒙-list组件和AlphabetIndexer组件带你实现通讯录,让你快速找到女朋友电话哦!

291 阅读5分钟

鸿蒙-list组件和AlphabetIndexer组件带你实现通讯录,让你快速找到女朋友电话哦!

内容讲的不对或有缺失,大家可以提提建议,谢谢!

list组件和AlphabetIndexer组件结合实现的通讯录,先让大家看一下效果成品效果哦

动画.gif

一、使用的场景

这两个组件,前者可以遍历内容,后者可以快速定位到我们所要选择的地方。两个组件的结合,我们可以实现通讯录列表的导航联动,以及快速定位的效果,上面的图大家可以更直观的看到。

二、组件的相关知识

接下来,我们讲讲list组件AlphabetIndexer组件这两个组件的用法、作用、属性等相关的知识。下面我们将会先分开讲解单个组件的知识,最后会整合起来展示一个综合的案例来展示给大家。

1、List组件知识

List容器组件里面包含了两个子组件ListItemListItemGroup,在使用的过程中,我们需要注意以下两个点:

  1. ListItemGroup是作为分组容器使用的。
  2. ListItem是作为List或者ListItemGroup的子组件使用的。

语法

//最顶层的组件容器
List(){
  //ListItem可以在ListItemGroup外使用,也可在里面使用
  ListItem(){}
  ListItemGroup(){
    ListItem(){}
    ListItem(){}
  }
}

1.1、List容器组件

这个组件我们通常用在多条内容需要输出的列表中,当内容超出屏幕大小的时候,它可以实现列表的滚动,在日常开发中我们还可以用它来实现更为复杂的效果,比如下图的分组展示:

List 组件.webp

List组件的用法

我们通过在List组件中按垂直或者水平的方向线性排列子组件。

设置主轴的方向

属性:listDirection(参数) 参数:枚举Axis

  • Vertical 垂直,默认
  • Horizontal 水平

语法

List() {
  listItem()
  ......
}
.listDirection(Axis.Vertical/Horizontal)  // 可写可不写

设置交叉轴的布局

属性:lanes(参数1,参数2)

参数:

  • 参数1 交叉轴方向列数
  • 参数2 交叉轴方向列间距

语法

List() {
  listItem()
  ......
}
    // 参数1:交叉轴方向列数
    // 参数2: 交叉轴方向列间距
  .lanes(3, 10)

列对齐方式 List交叉轴方向宽度大于ListItem交叉轴宽度 *列数时,ListItem在List交叉轴方向的布局方式,默认为首部对齐。
属性:alignListItem()
参数:枚举 ListItemAlign

  • Start:首部对齐(默认)
  • Center:居中对齐
  • End:尾部对齐

语法

List() {
  listItem()
  ......
}
    .alignListItem(ListItemAlign.Center)

1.2、ListItemGroup组件

这个配合List容器组件使用,它主要作为当做ListItem组件头部使用。

参数

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

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

参数名参数类型必填参数描述
headerCustomBuilder设置ListItemGroup头部组件。
footerCustomBuilder设置ListItemGroup尾部组件。
spacenumber 、 string列表项间距。只作用于ListItem与ListItem之间,不作用于header与ListItem、footer与ListItem之间。

它属性,和 List 是一样的

 .divider({
     strokeWidth: 1,  //分割线的线宽
     color: Color.Orange, //分割线的颜色
     startMargin:40//分割线距离列表侧边起始端的距离
     endMargin: 40       //分割线距离列表侧边结束端的距离。
 }) 

1.3、粘性标题

通过List组件的sticky属性,即可实现粘性标题

image.png

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

语法

List(){
  
}
  // .sticky(StickyStyle.None) // 不吸附 默认值
  // .sticky(StickyStyle.Header) // 头部吸附
  // .sticky(StickyStyle. Footer) //  底部吸附,如果有的话

1.4 控制滚动

当我们传入的数据过多时,列表会很长,这时我们需要快速滚动到列表底部或返回列表顶部,就可以使用代码来控制滚动。

关键步骤:

  1. 创建控制器(ListScroller)对象
  2. 设置给 List 组件
  3. 调用控制器对象的方法,实现滚动
// 1. 创建控制器(ListScroller)对象
listScroller: ListScroller = new ListScroller()
// 2. 设置给 List 组件
List({ space: 20, scroller: this.listScroller }) {
  // ...
}


Button() {
  // ...
}
.onClick(() => {
  // 3. 调用控制器对象的方法,实现滚动
  this.listScroller.scrollToIndex(0)
})

参数:

参数名参数类型必填参数描述
indexnumber要滑动到的目标元素所在的ListItemGroup在当前容器中的索引值。
smoothboolean设置滑动到列表项在列表中的索引值时是否有动效,true表示有动效,false表示没有动效。默认值:false。
alignScrollAlign指定滑动到的元素与当前容器的对齐方式。默认值:ScrollAlign.START。

1.5事件

List 组件提供了很多事件供咱们使用,目前掌握一个即可onScrollIndex,其他的事件后续结合业务逻辑再进行补充

名称功能描述
onScrollIndex(event: (start: number, end: number, center10+: number) => void)有子组件划入或划出List显示区域时触发。从API version 10开始,List显示区域中间位置子组件变化时也会触发。 计算索引值时,ListItemGroup作为一个整体占一个索引值,不计算ListItemGroup内部ListItem的索引值。

语法

    List(){
      // ...
    }
    .onScrollIndex((index: number) => {
      console.log('index:', index)
    })

2、AlphabetIndexer组件

用于实现根据字母索引对列表数据进行分组和排序的功能,并提供快速导航的能力

2.1 使用场景

AlphabetIndexer组件适用于需要对大量数据进行分组和排序展示的场景,如:

  • 联系人列表
  • 城市选择列表
  • 歌曲列表
  • 书籍目录
  • 商品分类等

在这些场景中,AlphabetIndexer组件可以提供快速导航和搜索功能,方便用户快速找到目标数据。例如,在城市选择场景中,可以在List组件中展示所有城市,同时在右侧使用AlphabetIndexer组件显示城市首字母索引。用户点击索引时,List组件会滚动到对应首字母的城市分组位置。

动画.gif

2.2 用法

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

image.png

struct ContactsList {
  alphabets: 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']

  build() {
    Stack({ alignContent: Alignment.End }) {
      // 字母表索引组件
      AlphabetIndexer({
        arrayValue: this.alphabets, 
        selected: $$this.selectedIndex
    })
  
    }
    .width('100%')
    .height('100%')
  }
}

注意:

通过双向绑定变量。可以实现修改变量值,同步更新选中的索引

2.3 外观设置

选中AlphabetIndexer,如果默认的颜色效果无法满足要求,可以通过如下属性来进行设置

名称参数类型描述
colorResourceColor设置文字颜色。 默认值:0x99000000。
selectedColorResourceColor设置选中项文字颜色。 默认值:0xFF254FF7。
selectedBackgroundColorResourceColor设置选中项背景颜色。 默认值:0x1F0A59F7。

用法

struct ContactsList {
  alphabets: 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']

  build() {
    Stack({ alignContent: Alignment.End }) {
      // 字母表索引组件
      AlphabetIndexer({ arrayValue: this.alphabets, selected: 0 })
        .color(Color.Orange)// 文字颜色
        .selectedColor(Color.Green)// 选中文字颜色
        .selectedBackgroundColor(Color.Black) // 选中背景颜色
    }
    .width('100%')
    .height('100%')
  }
}

2.4 弹窗提示

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

名称参数类型描述
usingPopupboolean设置是否使用提示弹窗。默认值:false。
popupBackgroundResourceColor设置提示弹窗背景色。默认值:0xFFFFFFFF。
popupColorResourceColor设置提示弹窗文字颜色。默认值:0xFF254FF7。

用法

struct ContactsList {
  alphabets: 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']

  build() {
    Stack({ alignContent: Alignment.End }) {
      // 字母表索引组件
      AlphabetIndexer({ arrayValue: this.alphabets, selected: 0 })
        .usingPopup(true)
        .popupColor(Color.Orange)// 弹窗文字颜色
        .popupBackground(Color.Pink)
    }
    .width('100%')
    .height('100%')
  }
}

2.5 事件

支持的常用事件是onSelect,会在选中不同项时触发

名称功能描述
onSelect(callback: (index: number) => void)8+索引条选中回调,返回值为当前选中索引。

三、案例-通讯录

动画.gif

interface ContactContent {
  initial: string
  nameList: string[]
}

@Entry
@Component
struct ContactsList {
  listScroller: ListScroller = new ListScroller()
  contacts: ContactContent[] = [
    { initial: 'A', nameList: ['阿猫', '阿狗', '阿虎', '阿龙', '阿鹰', '阿狼', '阿豹', '阿狮', '阿象', '阿鲸'] },
    { initial: 'B', nameList: ['白兔', '白鸽', '白鹤', '白鹭', '白狐', '白狼', '白虎', '白鹿', '白蛇', '白马'] },
    { initial: 'C', nameList: ['春花', '春风', '春雨', '春草', '春柳', '春燕', '春莺', '春蝶', '春蓝', '春绿'] },
    { initial: 'D', nameList: ['冬雪', '冬梅', '冬松', '冬竹', '冬云', '冬霜', '冬月', '冬夜', '冬青', '冬红'] },
    { initial: 'E', nameList: ['饿狼', '饿虎', '饿鹰', '饿豹', '饿熊', '饿蛇', '饿鱼', '饿虾', '饿蟹', '饿蚌'] },
    { initial: 'F', nameList: ['飞鸟', '飞鱼', '飞虫', '飞蜂', '飞蝶', '飞蛾', '飞蝉', '飞蝗', '飞鼠', '飞猫'] },
    { initial: 'G', nameList: ['孤狼', '孤鹰', '孤虎', '孤豹', '孤蛇', '孤鲨', '孤鲸', '孤鹿', '孤雁', '孤鸿'] },
    { initial: 'H', nameList: ['海鸥', '海龟', '海豚', '海星', '海马', '海葵', '海参', '海胆', '海螺', '海贝'] },
    { initial: 'I', nameList: ['火焰', '火球', '火箭', '火山', '火车', '火柴', '火把', '火鸟'] },
    { initial: 'J', nameList: ['金鱼', '金狮', '金刚', '金鹿', '金蛇', '金鹰', '金豹', '金虎', '金狐', '金猫'] },
    { initial: 'K', nameList: ['孔雀', '恐龙', '开心', '开怀', '开朗', '开拓', '开口', '开花', '开眼', '开天'] },
    { initial: 'L', nameList: ['老虎', '老鹰', '老鼠', '老狼', '老狗', '老猫', '老熊', '老鹿', '老龟', '老蛇'] },
    { initial: 'M', nameList: ['玫瑰', '牡丹', '梅花', '茉莉', '木兰', '棉花', '蜜蜂', '蚂蚁', '马蜂', '蟒蛇'] },
    { initial: 'N', nameList: ['南山', '南极', '南海', '南京', '南阳', '南风', '南瓜', '南竹', '南花', '南鸟'] },
    {
      initial: 'O',
      nameList: ['熊猫', '欧鹭', '欧洲', '欧阳', '欧文', '欧若拉', '欧米茄', '欧罗巴', '欧菲莉亚', '欧瑞斯']
    },
    { initial: 'P', nameList: ['苹果', '葡萄', '琵琶', '枇杷', '菩提', '瓢虫', '瓢泼', '飘零', '飘渺', '飘飘然'] },
    { initial: 'Q', nameList: ['七喜', '强风', '奇迹', '乾坤', '奇才', '晴天', '青竹', '秋水', '轻舞', '清泉'] },
    { initial: 'R', nameList: ['瑞雪', '瑞兽', '瑞光', '瑞云', '瑞彩', '瑞气', '瑞香', '瑞草', '瑞莲', '瑞竹'] },
    { initial: 'S', nameList: ['三羊', '三狗', '三猫', '三鱼', '三角', '三鹿', '三鹰', '三蛇', '三狐', '三豹'] },
    { initial: 'T', nameList: ['太阳', '天空', '田园', '太极', '太湖', '天鹅', '太空', '天使', '坦克', '甜橙'] },
    { initial: 'U', nameList: ['乌鸦', '乌鹊', '乌鱼', '乌龟', '乌云', '乌梅', '乌木', '乌金', '乌黑', '乌青'] },
    { initial: 'V', nameList: ['五虎', '五狼', '五鹰', '五豹', '五熊', '五蛇', '五鲨', '五鲸', '五鹿', '五马'] },
    { initial: 'W', nameList: ['悟空', '微笑', '温暖', '无畏', '温柔', '舞蹈', '问心', '悟道', '未来', '文学'] },
    { initial: 'X', nameList: ['西风', '西洋', '西子', '西施', '西岳', '西湖', '西柚', '西竹', '西花', '西鸟'] },
    { initial: 'Y', nameList: ['夜猫', '夜鹰', '夜莺', '夜空', '夜色', '夜月', '夜影', '夜翼', '夜狐', '夜狼'] },
    { initial: 'Z', nameList: ['珍珠', '紫薇', '紫霞', '紫竹', '紫云', '紫燕', '紫鸢', '紫藤', '紫荆', '紫罗兰'] },
  ]
  @State selIndex: number = 0
  alphabets: 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']

  build() {
    Stack({ alignContent: Alignment.End }) {
      List({ scroller: this.listScroller }) {
        // 循环
        // 参数 1:循环的数据,item 是每一项
        // 参数 2:箭头函数 (每一项的数据,下标)=>{}
        // 写好循环-》箭头函数先写个空-》填充参数
        ForEach(this.contacts, (item: ContactContent, index: number) => {
          ListItemGroup({
            header: this.headerBuilder(item.initial)
          }) {
            ForEach(item.nameList, (name: string, i: number) => {
              ListItem() {
                Row() {
                  Image($r('app.media.ic_public_lianxiren'))
                    .fillColor(Color.Orange)
                    .width(40)
                  Text(name)
                }
              }
            })
          }
          .divider({
            strokeWidth: 2,
            color: '#ccc'
          })

        })
      }
      .sticky(StickyStyle.Header)
      .onScrollIndex((star: number) => {
        this.selIndex = star
      })

      // 字母表索引组件
      AlphabetIndexer({ arrayValue: this.alphabets, selected: $$this.selIndex })
        .usingPopup(true)
        .popupColor(Color.Orange)
        .popupBackground(Color.Pink)
        .onSelect((index: number) => {
          console.log('index:', index)
          this.listScroller.scrollToIndex(index)
        })
    }
    .width('100%')
    .height('100%')
  }

  @Builder
  // title 形参的名字,叫什么都可以,有意义即可
  // string 约束类型
  headerBuilder(title: string) {
    Text(title)// 内部使用 形参
      .fontWeight(900)
      .fontSize(20)
      .backgroundColor('#ccc')
      .width('100%')
  }
}