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

获取当前List控件,第一个可见Item的位置 HarmonyOS 鸿蒙Next 现在有一个List组件
他滚动到了某个位置。我想知道目前第一个可见的Item,和最后一个可见的Item的位置。请问该如何获取?

Andorid系统上有该功能实现。
LinearLayoutManager.findFirstVisibleItemPosition();

3 回复

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 })
    }
  }
}

更多关于获取当前List控件,第一个可见Item的位置 HarmonyOS 鸿蒙Next的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,获取List控件中第一个可见Item的位置可以通过ListControllergetFirstVisibleItemIndex方法实现。ListController是List控件的控制器,用于管理和操作List的视图和布局。getFirstVisibleItemIndex方法返回当前可见区域内第一个Item的索引值。

示例代码如下:

let listController: ListController = ...; // 获取ListController实例
let firstVisibleIndex: number = listController.getFirstVisibleItemIndex();
console.log("第一个可见Item的索引:", firstVisibleIndex);

该方法直接返回当前List控件中第一个可见Item的索引,无需额外处理。适用于需要动态获取List控件可见区域内容的场景。

回到顶部