HarmonyOS鸿蒙Next中如何使用Refresh组件实现列表的下拉刷新功能?

HarmonyOS鸿蒙Next中如何使用Refresh组件实现列表的下拉刷新功能? 我想为列表添加下拉刷新功能,想了解:

  1. Refresh 组件如何包裹 List 实现下拉刷新?
  2. onRefreshing 回调如何处理刷新逻辑?
  3. refreshing 属性如何控制刷新状态的显示和隐藏?
  4. 如何自定义下拉刷新的 UI 样式?
  5. 如何实现下拉刷新 + 上拉加载更多的组合功能?

希望能获取下拉刷新的完整实现代码。

3 回复

实现思路:

  1. 使用 Refresh 组件包裹 List,通过 refreshing 属性控制刷新状态:
@State isRefreshing: boolean = false;

Refresh({ refreshing: $$this.isRefreshing }) {
  List() {
    // 列表内容
  }
}
  1. 在 onRefreshing 回调中处理刷新逻辑,完成后设置 refreshing 为 false:
.onRefreshing(async () => {
  await this.refreshData();
  this.isRefreshing = false;
})
  1. 结合 onReachEnd 实现上拉加载更多:
List()
  .onReachEnd(() => {
    this.loadMore();
  })
  1. 完整示例代码:
@Entry
@Component
struct RefreshExample {
  @State dataList: DataItem[] = [];
  @State isRefreshing: boolean = false;
  @State isLoadingMore: boolean = false;
  @State hasMore: boolean = true;
  private page: number = 1;

  async aboutToAppear() {
    await this.loadData();
  }

  async loadData(): Promise<void> {
    this.page = 1;
    this.dataList = await this.fetchData(this.page);
    this.hasMore = true;
  }

  async refreshData(): Promise<void> {
    this.page = 1;
    this.dataList = await this.fetchData(this.page);
    this.hasMore = true;
  }

  async loadMore(): Promise<void> {
    if (this.isLoadingMore || !this.hasMore) return;

    this.isLoadingMore = true;
    this.page++;
    const newData = await this.fetchData(this.page);

    if (newData.length === 0) {
      this.hasMore = false;
    } else {
      this.dataList = [...this.dataList, ...newData];
    }
    this.isLoadingMore = false;
  }

  async fetchData(page: number): Promise<DataItem[]> {
    return new Promise((resolve) => {
      setTimeout(() => {
        const items: DataItem[] = [];
        for (let i = 0; i < 10; i++) {
          items.push({
            id: `${page}-${i}`,
            name: `Item ${(page - 1) * 10 + i + 1}`
          });
        }
        resolve(items);
      }, 1000);
    });
  }

  build() {
    Column() {
      Refresh({ refreshing: $$this.isRefreshing }) {
        List({ space: 8 }) {
          ForEach(this.dataList, (item: DataItem) => {
            ListItem() {
              Text(item.name)
                .width('100%')
                .padding(16)
                .backgroundColor('#FFF')
                .borderRadius(8)
            }
          }, (item: DataItem) => item.id)

          // 加载更多
          ListItem() {
            Row() {
              if (this.isLoadingMore) {
                LoadingProgress().width(20).height(20)
                Text('加载中...').margin({ left: 8 })
              } else if (!this.hasMore) {
                Text('没有更多了').fontColor('#999')
              }
            }
            .width('100%')
            .height(50)
            .justifyContent(FlexAlign.Center)
          }
        }
        .width('100%')
        .height('100%')
        .padding(16)
        .onReachEnd(() => this.loadMore())
      }
      .onRefreshing(async () => {
        await this.refreshData();
        this.isRefreshing = false;
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

interface DataItem {
  id: string;
  name: string;
}

更多关于HarmonyOS鸿蒙Next中如何使用Refresh组件实现列表的下拉刷新功能?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用Refresh组件实现列表下拉刷新功能,需在ArkUI中通过@State装饰器管理刷新状态。将Refresh组件作为父容器包裹List组件,通过onRefresh回调触发数据刷新操作,并在异步数据加载完成后调用finishRefresh方法结束刷新状态。

在HarmonyOS Next中,使用Refresh组件实现列表下拉刷新功能,核心是将其作为List的父容器。以下是针对你问题的具体实现方案和代码示例。

1. Refresh 包裹 List 的基本结构

Refresh组件通过refreshing属性控制刷新状态,并使用onRefresh回调(对应你提到的onRefreshing)触发数据加载。基本结构如下:

import { Refresh, List, ListItem } from '@kit.ArkUI';

@Entry
@Component
struct RefreshExample {
  @State isRefreshing: boolean = false; // 控制刷新状态
  private data: string[] = ['Item 1', 'Item 2', 'Item 3']; // 示例数据

  build() {
    Refresh({
      refreshing: this.isRefreshing,
      onRefresh: () => {
        this.isRefreshing = true;
        // 模拟数据加载,2秒后结束刷新
        setTimeout(() => {
          this.data.unshift('New Item'); // 添加新数据
          this.isRefreshing = false;
        }, 2000);
      }
    }) {
      List() {
        ForEach(this.data, (item: string) => {
          ListItem() {
            Text(item).fontSize(20).margin(10)
          }
        })
      }
    }
  }
}

2. onRefreshing 回调处理逻辑

onRefresh回调在用户下拉时触发,通常在此处执行网络请求或本地数据加载。示例中通过setTimeout模拟异步操作,实际开发需替换为具体数据逻辑(如fetch请求)。刷新完成后,必须将refreshing设为false以隐藏加载指示器。

3. refreshing 属性控制状态

  • refreshing: true:显示加载指示器,禁用下拉操作。
  • refreshing: false:隐藏指示器,恢复下拉功能。 通过@State变量动态绑定此属性,即可实现状态同步。

4. 自定义下拉刷新 UI

Refresh组件支持通过builder属性完全自定义下拉区域样式。例如,替换默认指示器为文字和图标:

Refresh({
  refreshing: this.isRefreshing,
  onRefresh: () => { /* 刷新逻辑 */ },
  builder: (refreshState: RefreshStatus) => {
    // 根据状态显示不同内容
    if (refreshState === RefreshStatus.Inactive) {
      return Text('下拉刷新').fontColor('#666');
    } else if (refreshState === RefreshStatus.Drag) {
      return Text('释放刷新').fontColor('#007DFF');
    } else {
      return Row() {
        LoadingProgress().width(20).height(20);
        Text('加载中...').margin({ left: 10 });
      };
    }
  }
}) {
  List() { /* 列表内容 */ }
}

RefreshStatus枚举提供Inactive(未激活)、Drag(下拉中)、Refresh(刷新中)等状态,可用于精细化UI控制。

5. 下拉刷新 + 上拉加载更多

需结合RefreshListonReachEnd回调实现。示例:

@State isRefreshing: boolean = false;
@State isLoadingMore: boolean = false;
private data: string[] = [...];
private page: number = 1;

build() {
  Refresh({
    refreshing: this.isRefreshing,
    onRefresh: () => {
      this.isRefreshing = true;
      // 下拉刷新:重置数据
      this.page = 1;
      this.loadData(true);
    }
  }) {
    List({ space: 10 }) {
      ForEach(this.data, (item) => {
        ListItem() { Text(item) }
      })
      // 上拉加载更多提示
      if (this.isLoadingMore) {
        ListItem() {
          Row() {
            LoadingProgress();
            Text('加载更多...').margin({ left: 10 });
          }.justifyContent(FlexAlign.Center).width('100%').padding(20)
        }
      }
    }
    .onReachEnd(() => {
      // 触发上拉加载
      if (!this.isLoadingMore) {
        this.isLoadingMore = true;
        this.page += 1;
        this.loadData(false);
      }
    })
  }
}

// 统一数据加载函数
loadData(isRefresh: boolean) {
  // 模拟网络请求
  setTimeout(() => {
    const newData = [`Page ${this.page} Item`];
    if (isRefresh) {
      this.data = newData; // 刷新时替换数据
    } else {
      this.data.push(...newData); // 加载更多时追加数据
    }
    this.isRefreshing = false;
    this.isLoadingMore = false;
  }, 1500);
}

关键点

  • 下拉刷新由RefreshonRefresh处理,通常重置页码并更新数据。
  • 上拉加载通过ListonReachEnd触发,需防止重复请求(示例中用isLoadingMore状态锁)。
  • 列表底部通过条件渲染显示加载提示。

完整示例代码

以下为整合下拉刷新、上拉加载及自定义UI的完整代码:

import { Refresh, List, ListItem, LoadingProgress, RefreshStatus } from '@kit.ArkUI';

@Entry
@Component
struct FullRefreshExample {
  @State isRefreshing: boolean = false;
  @State isLoadingMore: boolean = false;
  @State data: string[] = ['初始数据1', '初始数据2', '初始数据3'];
  private page: number = 1;

  build() {
    Refresh({
      refreshing: this.isRefreshing,
      onRefresh: () => {
        this.isRefreshing = true;
        this.page = 1;
        this.loadData(true);
      },
      builder: (refreshState: RefreshStatus) => {
        // 自定义下拉区域
        return Column() {
          if (refreshState === RefreshStatus.Refresh) {
            LoadingProgress().width(30).height(30);
            Text('拼命加载中...').fontSize(14).margin({ top: 8 });
          } else {
            Image($r('app.media.arrow_down'))
              .width(25)
              .rotate({ angle: refreshState === RefreshStatus.Drag ? 180 : 0 });
            Text(refreshState === RefreshStatus.Drag ? '释放刷新' : '下拉刷新')
              .fontSize(14)
              .margin({ top: 8 });
          }
        }.padding(15);
      }
    }) {
      List({ space: 5 }) {
        ForEach(this.data, (item: string, index?: number) => {
          ListItem() {
            Text(`${index + 1}. ${item}`)
              .fontSize(18)
              .padding(15)
              .backgroundColor('#FFF')
              .width('100%')
          }
        })
        
        // 上拉加载更多区域
        if (this.isLoadingMore) {
          ListItem() {
            Row() {
              LoadingProgress().width(20).height(20);
              Text('加载更多数据...').margin({ left: 10 });
            }
            .justifyContent(FlexAlign.Center)
            .width('100%')
            .padding(20)
          }
        }
      }
      .onReachEnd(() => {
        if (!this.isLoadingMore) {
          this.isLoadingMore = true;
          this.page += 1;
          this.loadData(false);
        }
      })
      .width('100%')
      .backgroundColor('#F1F1F1')
    }
  }

  loadData(isRefresh: boolean) {
    // 模拟异步请求
    setTimeout(() => {
      const newData = Array.from({ length: 3 }, (_, i) => 
        `第${this.page}页数据${i + 1}`
      );
      if (isRefresh) {
        this.data = newData;
      } else {
        this.data = [...this.data, ...newData];
      }
      this.isRefreshing = false;
      this.isLoadingMore = false;
    }, 2000);
  }
}

注意事项

  • 确保refreshing状态在数据加载完成后及时更新,避免界面卡死。
  • 上拉加载时建议添加数据为空或加载失败的占位提示。
  • 自定义builder时,可通过RefreshStatus枚举值适配不同状态下的UI表现。

以上代码可直接运行测试,根据实际需求调整数据加载逻辑和样式即可。

回到顶部