HarmonyOS鸿蒙Next中如何在应用中实现列表展示和滚动?

HarmonyOS鸿蒙Next中如何在应用中实现列表展示和滚动? 如何在鸿蒙应用中展示大量数据列表?如何实现列表滚动、下拉刷新和上拉加载?

3 回复

关键字:List、ListItem、ForEach、列表滚动、虚拟列表、性能优化

回答

原理解析

List组件是鸿蒙应用中展示大量数据的高性能组件,支持虚拟滚动和懒加载。

核心概念:

  1. List容器:包含多个ListItem的滚动容器
  2. ListItem:列表项,每个项可以包含自定义内容
  3. ForEach:循环渲染列表项
  4. 虚拟滚动:只渲染可见区域的项,提升性能

性能优化:

  • 使用唯一key标识列表项
  • 避免在ListItem中使用复杂布局
  • 使用缓存机制减少重建

详细解决步骤

步骤1:创建基础列表

List() {

  ForEach(this.items, (item: string) => {

    ListItem() {

      Text(item)

    }

  })

}

步骤2:添加滚动监听

List()

  .onScroll((scrollOffset: number, scrollState: ScrollState) => {

    console.info('滚动位置:', scrollOffset)

  })

步骤3:实现下拉刷新

List()

  .refresh(new Refresh())

  .onRefresh(() => {

    this.loadData()

  })

示例代码

完整示例:高性能列表

@Entry

@Component

struct ListDemo {

  @State items: Array<{id: string, title: string, subtitle: string}> = []

  @State isLoading: boolean = false

  @State hasMore: boolean = true

  private page: number = 1

  private pageSize: number = 20



  aboutToAppear() {

    this.loadData()

  }



  build() {

    Column() {

      Text('列表示例')

        .fontSize(24)

        .fontWeight(FontWeight.Bold)

        .padding(20)



      List({ space: 10 }) {

        ForEach(this.items, (item: {id: string, title: string, subtitle: string}) => {

          ListItem() {

            this.buildListItem(item)

          }

        }, (item: {id: string, title: string, subtitle: string}) => item.id)

      }

      .layoutWeight(1)

      .width('100%')

      .divider({ strokeWidth: 1, color: 'E5E5E5', startMargin: 20, endMargin: 20 })

      .scrollBar(BarState.Auto)

      .edgeEffect(EdgeEffect.Spring)

      .onReachEnd(() => {

        if (this.hasMore && !this.isLoading) {

          this.loadMore()

        }

      })

      .onScroll((scrollOffset: number) => {

        // 滚动监听

      })

    }

    .width('100%')

    .height('100%')

    .backgroundColor('F1F3F5')

  }



  @Builder

  buildListItem(item: {id: string, title: string, subtitle: string}) {

    Row({ space: 15 }) {

      // 图标

      Text('��')

        .fontSize(32)



      // 内容

      Column({ space: 5 }) {

        Text(item.title)

          .fontSize(16)

          .fontWeight(FontWeight.Medium)

          .fontColor('182431')

        

        Text(item.subtitle)

          .fontSize(14)

          .fontColor('666666')

      }

      .layoutWeight(1)

      .alignItems(HorizontalAlign.Start)



      // 箭头

      Text('>')

        .fontSize(18)

        .fontColor('CCCCCC')

    }

    .width('100%')

    .padding(15)

    .backgroundColor('FFFFFF')

    .borderRadius(8)

    .onClick(() => {

      console.info('点击项:', item.id)

    })

  }



  // 加载数据

  private loadData(): void {

    this.isLoading = true

    // 模拟网络请求

    setTimeout(() => {

      this.items = this.generateItems(1, this.pageSize)

      this.isLoading = false

    }, 500)

  }



  // 加载更多

  private loadMore(): void {

    if (this.isLoading || !this.hasMore) return

    

    this.isLoading = true

    this.page++

    

    // 模拟网络请求

    setTimeout(() => {

      const newItems = this.generateItems(this.page, this.pageSize)

      if (newItems.length === 0) {

        this.hasMore = false

      } else {

        this.items = this.items.concat(newItems)

      }

      this.isLoading = false

    }, 500)

  }



  // 生成测试数据

  private generateItems(page: number, size: number): Array<{id: string, title: string, subtitle: string}> {

    const items: Array<{id: string, title: string, subtitle: string}> = []

    const start = (page - 1) * size

    

    for (let i = 0; i < size; i++) {

      const index = start + i

      if (index >= 100) break // 限制总数

      

      items.push({

        id: `item_${index}`,

        title: `列表项 ${index + 1}`,

        subtitle: `这是第 ${index + 1} 项的详细描述信息`

      })

    }

    

    return items

  }

}

高级用法

  1. 下拉刷新
List()

  .refresh(new Refresh())

  .onRefresh(() => {

    this.page = 1

    this.items = []

    this.loadData()

  })
  1. 分组列表
List() {

  ForEach(this.groups, (group: Group) => {

    ListItemGroup({ header: this.groupHeader(group.title) }) {

      ForEach(group.items, (item: Item) => {

        ListItem() {

          this.buildItem(item)

        }

      })

    }

  })

}
  1. 多选列表
@State selectedItems: string[] = []



ListItem() {

  // 内容

}

.selected(this.selectedItems.includes(item.id))

.onSelect((isSelected: boolean) => {

  if (isSelected) {

    this.selectedItems.push(item.id)

  } else {

    this.selectedItems = this.selectedItems.filter(id => id !== item.id)

  }

})

常见问题

Q: 列表滚动卡顿怎么办?

A: 使用唯一key、简化ListItem布局、避免在滚动过程中进行复杂计算。

Q: 如何实现无限滚动?

A: 使用onReachEnd事件监听滚动到底部,然后加载更多数据。

Q: List和Scroll有什么区别?

A: List针对列表场景优化,支持虚拟滚动;Scroll是通用滚动容器。

总结:List组件是展示大量数据的最佳选择,掌握其使用方法和性能优化技巧是开发流畅应用的关键。

更多关于HarmonyOS鸿蒙Next中如何在应用中实现列表展示和滚动?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用ArkUI框架的List组件实现列表展示和滚动。通过ForEach渲染列表项,List组件内置滚动能力,无需额外配置。支持垂直和水平滚动方向。示例代码结构如下:

@Entry
@Component
struct MyList {
  private data: string[] = ['Item1', 'Item2', 'Item3']

  build() {
    List() {
      ForEach(this.data, (item: string) => {
        ListItem() {
          Text(item)
        }
      })
    }
  }
}

在HarmonyOS Next中,实现列表展示和滚动主要使用List组件。以下是核心实现方法:

1. 基础列表展示与滚动 使用List组件,并通过ForEach渲染数据项。列表默认支持垂直滚动。

List() {
  ForEach(this.dataArray, (item: DataItem) => {
    ListItem() {
      // 自定义列表项UI,例如:
      Text(item.name).fontSize(16)
    }
  })
}
.listDirection(Axis.Vertical) // 设置滚动方向,默认可不写

2. 性能优化:LazyForEach 当数据量极大时,应使用LazyForEach进行延迟加载,避免一次性渲染所有项造成内存压力。

LazyForEach(this.dataSource, (item: DataItem) => {
  ListItem() {
    Text(item.name)
  }
})

3. 下拉刷新 使用Refresh组件包裹List,并通过onRefresh回调触发数据刷新。

Refresh({
  refreshing: this.isRefreshing, // 控制刷新状态
  onRefresh: () => {
    // 执行刷新数据的逻辑
    this.fetchNewData();
  }
}) {
  List() { ... }
}

4. 上拉加载更多 通过onReachEnd事件监听列表滚动到底部,并加载更多数据。

List() {
  // ...列表内容
}
.onReachEnd(() => {
  if (!this.isLoading) {
    this.loadMoreData(); // 加载下一页数据
  }
})

5. 关键属性

  • .scrollBar(BarState.Auto) 控制滚动条显示
  • .edgeEffect(EdgeEffect.Spring) 设置滚动到边缘时的效果
  • .divider() 设置列表项分割线

注意事项

  • 确保每个列表项有稳定的唯一键值(id),尤其在LazyForEach中。
  • 复杂列表项建议使用@Reusable装饰器优化复用性能。
  • 下拉刷新与上拉加载的状态需要手动管理(如加载中、无更多数据等)。

这种实现方式兼顾了功能完整性与性能,是处理HarmonyOS Next中长列表的标准方案。

回到顶部