img

一、案例介绍

本案例将展示如何在列表组件中使用LoadingProgress组件实现下拉刷新和加载更多功能。通过合理的状态管理和动画过渡,为用户提供流畅的列表数据加载体验。

二、实现效果

  • 支持下拉刷新数据
  • 实现上拉加载更多
  • 展示加载状态动画
  • 优雅处理加载失败

三、代码实现

1. 数据结构

interface ListItem {
  id: number;
  title: string;
  description: string;
}

@Entry
@Component
struct LoadingList {
  @State dataList: ListItem[] = [];
  @State isRefreshing: boolean = false;
  @State isLoadingMore: boolean = false;
  @State hasMore: boolean = true;
  private pageSize: number = 10;
  private currentPage: number = 1;

  aboutToAppear() {
    this.loadInitialData();
  }

  build() {
    Column() {
      Refresh({
        refreshing: $$this.isRefreshing,
        friction: RefreshFriction.Normal,
        onRefresh: () => this.onRefresh()
      }) {
        this.ListContent()
      }
    }
    .width('100%')
    .height('100%')
  }
}

2. 列表内容实现

@Builder
ListContent() {
  List() {
    ForEach(this.dataList, (item) => {
      ListItem() {
        this.ListItemContent(item)
      }
    })

    if (this.hasMore) {
      ListItem() {
        this.LoadMoreFooter()
      }
    }
  }
  .width('100%')
  .height('100%')
  .onReachEnd(() => {
    if (this.hasMore && !this.isLoadingMore) {
      this.loadMore();
    }
  })
}

@Builder
ListItemContent(item: ListItem) {
  Column() {
    Text(item.title)
      .fontSize(16)
      .fontWeight(FontWeight.Medium)
    
    Text(item.description)
      .fontSize(14)
      .fontColor('#666666')
      .margin({ top: 4 })
  }
  .width('100%')
  .padding(16)
  .backgroundColor(Color.White)
  .borderRadius(8)
  .margin({ bottom: 8 })
}

@Builder
LoadMoreFooter() {
  Row() {
    if (this.isLoadingMore) {
      LoadingProgress()
        .width(20)
        .height(20)
        .color('#666666')
        .margin({ right: 8 })
      Text('加载中...')
        .fontSize(14)
        .fontColor('#666666')
    }
  }
  .width('100%')
  .height(48)
  .justifyContent(FlexAlign.Center)
}

3. 数据加载逻辑

private async loadInitialData() {
  try {
    const data = await this.fetchData(1);
    this.dataList = data;
    this.currentPage = 1;
    this.hasMore = data.length === this.pageSize;
  } catch (error) {
    this.showError('加载失败');
  }
}

private async onRefresh() {
  if (this.isRefreshing) return;
  
  try {
    const data = await this.fetchData(1);
    this.dataList = data;
    this.currentPage = 1;
    this.hasMore = data.length === this.pageSize;
  } catch (error) {
    this.showError('刷新失败');
  } finally {
    this.isRefreshing = false;
  }
}

private async loadMore() {
  if (this.isLoadingMore || !this.hasMore) return;
  
  this.isLoadingMore = true;
  
  try {
    const nextPage = this.currentPage + 1;
    const data = await this.fetchData(nextPage);
    
    if (data.length > 0) {
      this.dataList = this.dataList.concat(data);
      this.currentPage = nextPage;
      this.hasMore = data.length === this.pageSize;
    } else {
      this.hasMore = false;
    }
  } catch (error) {
    this.showError('加载更多失败');
  } finally {
    this.isLoadingMore = false;
  }
}

private fetchData(page: number): Promise<ListItem[]> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟数据生成
      const startIndex = (page - 1) * this.pageSize;
      const data = Array.from({ length: this.pageSize }, (_, index) => ({
        id: startIndex + index + 1,
        title: `标题 ${startIndex + index + 1}`,
        description: `这是第 ${startIndex + index + 1} 条数据的详细描述信息`
      }));
      
      // 模拟数据加载完成
      if (page > 5) {
        resolve([]);
      } else {
        resolve(data);
      }
    }, 1000);
  });
}

private showError(message: string) {
  AlertDialog.show({
    title: '错误',
    message: message,
    confirm: {
      value: '确定',
      action: () => {
        AlertDialog.hide();
      }
    }
  });
}

四、总结

本案例通过在列表组件中使用 LoadingProgress 组件,实现了下拉刷新和上拉加载更多的功能。通过合理的状态管理和动画过渡,为用户提供了流畅的列表数据加载体验。这种实现方式适用于需要动态加载数据的列表场景,能够有效提升用户的交互体验。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐