HarmonyOS 鸿蒙Next中求问,这种样式的侧边索引条是如何实现的呢?

HarmonyOS 鸿蒙Next中求问,这种样式的侧边索引条是如何实现的呢?

我看了AlphabetIndexer(),在方表盘上显示的内容过多,没有向下箭头显示
ArcAlphabetIndexer()适配圆形表盘的

6 回复

更多关于HarmonyOS 鸿蒙Next中求问,这种样式的侧边索引条是如何实现的呢?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这个用官方组件AlphabetIndexer来处理的参考文档: AlphabetIndexer-信息展示-ArkTS组件-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

代码示例:

// xxx.ets
@Entry
@Component
struct AlphabetIndexerSample {
  private arrayA: string[] = ['安'];
  private arrayB: string[] = ['卜', '白', '包', '毕', '丙'];
  private arrayC: string[] = ['曹', '成', '陈', '催'];
  private arrayJ: string[] = ['嘉', '贾'];
  private value: 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'];
  @State isNeedAutoCollapse: boolean = false;
  @State indexerHeight: string = '75%';

  build() {
    Stack({ alignContent: Alignment.Start }) {
      Row() {
        List({ space: 20, initialIndex: 0 }) {
          ForEach(this.arrayA, (item: string) => {
            ListItem() {
              Text(item)
                .width('80%')
                .height('5%')
                .fontSize(30)
                .textAlign(TextAlign.Center)
            }
          }, (item: string) => item)

          ForEach(this.arrayB, (item: string) => {
            ListItem() {
              Text(item)
                .width('80%')
                .height('5%')
                .fontSize(30)
                .textAlign(TextAlign.Center)
            }
          }, (item: string) => item)

          ForEach(this.arrayC, (item: string) => {
            ListItem() {
              Text(item)
                .width('80%')
                .height('5%')
                .fontSize(30)
                .textAlign(TextAlign.Center)
            }
          }, (item: string) => item)

          ForEach(this.arrayJ, (item: string) => {
            ListItem() {
              Text(item)
                .width('80%')
                .height('5%')
                .fontSize(30)
                .textAlign(TextAlign.Center)
            }
          }, (item: string) => item)
        }
        .width('50%')
        .height('100%')

        Column() {
          Column() {
            AlphabetIndexer({ arrayValue: this.value, selected: 0 })
              .autoCollapse(this.isNeedAutoCollapse) // 开启或关闭自适应折叠模式
              .height(this.indexerHeight) // 索引条高度
              .enableHapticFeedback(false) // 关闭触控反馈
              .selectedColor(0xFFFFFF) // 选中项文本颜色
              .popupColor(0xFFFAF0) // 提示弹窗一级索引文本颜色
              .selectedBackgroundColor(0xCCCCCC) // 选中项背景颜色
              .popupBackground(0xD2B48C) // 提示弹窗背景颜色
              .usingPopup(true) // 索引项被选中时显示提示弹窗
              .selectedFont({ size: 16, weight: FontWeight.Bolder }) // 选中项文本样式
              .popupFont({ size: 30, weight: FontWeight.Bolder }) // 提示弹窗内容的文本样式
              .itemSize(28) // 每一项的尺寸大小
              .alignStyle(IndexerAlign.Right) // 提示弹窗在索引条左侧弹出
              .popupTitleBackground("#D2B48C") // 设置提示弹窗一级索引项背景颜色
              .popupSelectedColor(0x00FF00) // 提示弹窗二级索引未选中项文本颜色
              .popupUnselectedColor(0x0000FF) // 提示弹窗二级索引选中项文本颜色
              .popupItemFont({ size: 30, style: FontStyle.Normal }) // 提示弹窗二级索引项文本样式
              .popupItemBackgroundColor(0xCCCCCC) // 提示弹窗二级索引项背景颜色
              .onSelect((index: number) => {
                console.info(this.value[index] + ' Selected!');
              })
              .onRequestPopupData((index: number) => {
                // 当选中A时,提示弹窗里面的二级索引文本列表显示A对应的列表arrayA,选中B、C、L时也同样
                // 选中其余索引项时,提示弹窗二级索引文本列表为空,提示弹窗会只显示一级索引项
                if (this.value[index] == 'A') {
                  return this.arrayA;
                } else if (this.value[index] == 'B') {
                  return this.arrayB;
                } else if (this.value[index] == 'C') {
                  return this.arrayC;
                } else if (this.value[index] == 'J') {
                  return this.arrayJ;
                } else {
                  return [];
                }
              })
              .onPopupSelect((index: number) => {
                console.info('onPopupSelected:' + index);
              })
          }
          .height('80%')
          .justifyContent(FlexAlign.Center)

          Column() {
            Button('切换成折叠模式')
              .margin('5vp')
              .onClick(() => {
                this.isNeedAutoCollapse = true;
              })
            Button('切换索引条高度到30%')
              .margin('5vp')
              .onClick(() => {
                this.indexerHeight = '30%';
              })
            Button('切换索引条高度到70%')
              .margin('5vp')
              .onClick(() => {
                this.indexerHeight = '70%';
              })
          }
          .height('20%')
        }
        .width('50%')
        .justifyContent(FlexAlign.Center)
      }
      .width('100%')
      .height(720)
    }
  }
}

箭头的效果楼主可以封装一下 限制高度和显式就好,这个效果的视线就是用这个组件做的,也可以自己高度封装一个,

鸿蒙Next中侧边索引条可通过以下方式实现:

  1. 使用ListContainer组件作为主容器
  2. 添加IndexBar组件实现索引功能
  3. 通过IndexBarController控制索引交互
  4. 在ListContainer的onIndexUpdate回调中处理索引变化

关键代码要点:

  • IndexBar需要设置indexes属性(字母数组)
  • 实现OnIndexSelectedListener接口处理选中事件
  • 使用scrollToIndex方法滚动到对应位置

样式可通过修改IndexBar的以下属性调整:

  • indexItemSize:索引项大小
  • selectedColor:选中颜色
  • normalColor:正常颜色

在HarmonyOS Next中实现这种带向下箭头的侧边索引条,可以通过自定义AlphabetIndexer组件实现。以下是关键实现思路:

  1. 继承AlphabetIndexer并重写onDraw方法,在绘制字母列表时添加向下箭头图标
  2. 使用Canvas绘制箭头图标,通常放在字母列表的底部
  3. 通过measureText计算字母占用空间,确保有足够空间显示箭头
  4. 处理触摸事件时,对箭头区域做特殊处理

核心代码示例:

class CustomIndexer extends AlphabetIndexer {
  private arrowHeight = 20 // 箭头高度

  onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    
    // 在底部绘制箭头
    const arrowY = this.height - this.arrowHeight
    canvas.drawArrow(/* 箭头绘制参数 */)
  }

  onTouchEvent(event: TouchEvent): boolean {
    const y = event.getY()
    // 检查是否点击了箭头区域
    if (y > this.height - this.arrowHeight) {
      this.handleArrowClick()
      return true
    }
    return super.onTouchEvent(event)
  }
}

这种实现方式既保留了原生索引功能,又增加了滚动到底部的快捷操作。

回到顶部