HarmonyOS 获取当前List控件,第一个可见Item的位置?

现在有一个List组件

他滚动到了某个位置。我想知道目前第一个可见的Item,和最后一个可见的Item的位置。请问该如何获取?

其他系统上有该功能实现。

LinearLayoutManager.findFirstVisibleItemPosition();
阅读 490
1 个回答

HarmonyOS没有可以直接获取第一个和最后一个完全可见元素的接口,需要使用onScrollIndex和OnScroll回调配合实现。onScrollIndex能获取当前窗口内所有可见的item,在onscrollstop中,通过获取可见item的坐标和父容器坐标的比较得到完全可见的item的index。

具体DEMO如下,以list中text左对齐为例:

@Entry
@Component
struct ListExample {
  private arr: number[] = []
  private scrollerForList: Scroller = new Scroller()
  @State startStr: string = ''

  startIndex = 0
  endIndex = 0
  initState = true
  rowWidth = 400
  private judgeVisible() {
    this.startStr = ""
    // 判断start是否遮挡
    let rect = this.scrollerForList.getItemRect(this.startIndex)
    // 左对齐的场景下,如果左边第一个元素完全可见,那么元素x坐标(相对row的坐标)误差在1以内
    if (!((-1 < rect.x) && (rect.x < 1)))
    {
      this.startIndex = this.startIndex + 1
    }
rect = this.scrollerForList.getItemRect(this.endIndex)
// 左对齐的场景下,如果右边第一个元素完全可见,那么元素x坐标加上元素宽度 应该在row的宽度范围之内(还需要考虑1px的误差)
if (!((rect.x + rect.width) > this.rowWidth - 1 && (rect.x + rect.width) < this.rowWidth + 1))
    {
      this.endIndex = this.endIndex - 1
    }
    if (this.startIndex <= this.endIndex) {
      this.startStr = String(this.startIndex) + "," + String(this.endIndex)
    }else {
      this.startStr = "没有能全部显示的控件"
    }
  }

  aboutToAppear() {
    for (let i = 0; i < 20; i++) {
      this.arr.push(i)
    }
  }
  build() {
    Column() {
      Row() {
        Text(this.startStr)
          .fontSize(10)
          .textAlign(TextAlign.Start)
          .fontColor(Color.Red)
      }
      .height(100)
      .backgroundColor(Color.Gray)
      .opacity(0.3)
      .width("100%")

      Row() {
        List({ space: 20, initialIndex: 0, scroller: this.scrollerForList }) {
          ForEach(this.arr, (item: number) => {
            ListItem() {
              Text('' + item)
                .width('100%').height(100).fontSize(16)
                .textAlign(TextAlign.Center)
            }
            .borderRadius(10).backgroundColor(0xFFFFFF)
            .width(item%4==0 ? 500 : 50)
            .height(200)
          }, (item: number) => JSON.stringify(item))
        }
        .chainAnimation(true)
        .edgeEffect(EdgeEffect.Spring)
        .listDirection(Axis.Horizontal)
        .height('100%')
        .width(this.rowWidth)
        .scrollSnapAlign(ScrollSnapAlign.START)
        .borderRadius(10)
        .backgroundColor(0xDCDCDC)
        .divider({ strokeWidth: 2, color: 0xFF00000, startMargin: 10, endMargin: 40 })
        .onScrollIndex((start, end)=>{
            this.startIndex = start
            this.endIndex = end

        // 界面初始显示的时候,不会触发onScrollStop事件,在这里判断可见性

            if (this.initState == true) {
              this.judgeVisible()
              this.initState = false
            }
        })
        .onScrollStop(()=>{

      // 缓存开始结束索引: 在最后一页多次右滑时候,不会触发onScrollIndex

          let tmpStart = this.startIndex
          let tmpEnd = this.endIndex
          this.judgeVisible()
          this.startIndex = tmpStart
          this.endIndex =tmpEnd
        })

      }
      .width('100%')
      .height('100%')
      .backgroundColor(0xDCDCDC)
      .padding({ top: 10 })
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进