145 Star 1.4K Fork 1.7K

OpenHarmony/applications_app_samples

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
.gitee
code
AI/MindSporeLiteCDemoASR
BasicFeature
DataMock
DocsSample
LanguageBaseClassLibrary
Performance
Project
Solutions
SuperFeature
SystemFeature
UI
ArkTsComponentCollection
CalendarViewSwitch
CitySearch
CustomAnimationTab
DragAndExchange
ExpandTitle
FoldableAdaptation
ImageViewer
Immersive
ImperativeDynamicLayouts
KeyboardAvoid
ListBeExchange
PageLoading
PullToRefresh
AppScope
entry
hvigor
pulltorefresh
.gitignore
README.md
build-profile.json5
code-linter.json5
hvigorfile.ts
oh-package.json5
ohosTest.md
SearchComponent
TabContentTouchHotZone
VerifyCode
WindowStartIcon
.gitattributes
.gitignore
CodeCommitChecklist.md
LICENSE
OAT.xml
README.md
README_zh.md
SampleReadTemplate.md
changelog.md
ohosTestTemplate.md
releasenote.md
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

下拉刷新与上滑加载案例

介绍

本示例介绍使用第三方库的PullToRefresh组件实现列表的下拉刷新数据和上滑加载后续数据。

效果图预览

使用说明

  1. 进入页面,下拉列表触发刷新数据事件,等待数据刷新完成。
  2. 上滑列表到底部,触发加载更多数据事件,等待数据加载完成。

实现思路

  1. 使用第三方库pullToRefresh组件,将列表组件、绑定的数据对象和scroller对象包含进去,并添加上滑与下拉方法。源码参考PullToRefreshNews.ets
    PullToRefresh({
      // 必传项,列表组件所绑定的数据
      data: $newsData,
      // 必传项,需绑定传入主体布局内的列表或宫格组件
      scroller: this.scroller,
      // 必传项,自定义主体布局,内部有列表或宫格组件
      customList: () => {
        // 一个用@Builder修饰过的UI方法
        this.getListView();
      },
      // 下拉刷新回调
      onRefresh: () => {
        return new Promise<string>((resolve, reject) => {
          ...
        });
      },
      // 上滑加载回调
      onLoadMore: () => {
        return new Promise<string>((resolve, reject) => {
          ...
        });
      },
      customLoad: () => this.customLoad(),
      customRefresh: null,
    })
    
  2. 使用LazyForEach循环渲染列表。源码参考PullToRefreshNews.ets
    LazyForEach(this.newsData, (item: NewsData) => {
      ListItem() {
        ...
      }
    });
    
  3. 模拟列表总页数,加载完全部信息后提示已经到底部。源码参考PullToRefreshNews.ets
    onLoadMore: () => {
      return new Promise<string>((resolve, reject) => { 
        // 模拟数据列表页超过4页后已到达底部,无法继续加载
        if (this.newsDataListIndex < NEWS_MAX_LIST) {
          // 模拟网络请求操作,请求网络1.5秒后得到数据,通知组件变更列表数据
          setTimeout(() => {
            let newsModelMockData: Array<NewsData> = getNews(MOCK_DATA_FILE_ONE_DIR)
            for (let j = 0; j < NEWS_MOCK_DATA_COUNT; j++) {
              this.newsData.pushData(newsModelMockData[j]);
            }
            this.newsDataListIndex++;
            resolve('');
          }, NEWS_REFRESH_TIME);
        } else {
            // 如果已满4页,更改上拉提示信息提示已经加载完所有数据
            setTimeout(() => {
            resolve('');
          }, NEWS_REFRESH_TIME);
        }
      });
    }
    
  4. 自定义下拉更新动画。源码参考PullToRefreshNews.ets
    @Builder
    private customRefresh() {
       Row() {
          // 下滑加载图片
          Image($r('app.media.pull_icon_load'))
             .width($r('app.string.pull_refresh_load_width'))
             .height($r('app.string.pull_refresh_load_height'))
             .objectFit(ImageFit.Contain)
             .rotate({
                z: 1,
                angle: this.angle2 !== undefined ? this.angle2 : 0
             })
             .width(this.refreshConfigurator.getLoadImgHeight())
             .height(this.refreshConfigurator.getLoadImgHeight())
       
          // 下拉时提示文本
          Stack() {
             Text(CURRENT_DATA_TIP)
                .height($r('app.string.pull_refresh_load_height'))
                .textAlign(TextAlign.Center)
                .margin({ left: this.newsDataListIndex === NEWS_MAX_LIST && this.isLoading ? 0 : 8 })
                .fontColor(this.refreshConfigurator !== undefined ? this.refreshConfigurator.getLoadTextColor() : 0)
                .fontSize(this.refreshConfigurator !== undefined ? this.refreshConfigurator.getLoadTextSize() : 0)
                .visibility(this.pullHeightValue <= CHANGE_PAGE_STATE ? Visibility.Visible : Visibility.Hidden)
             Text(NEW_DATA_TIP)
                .height($r('app.string.pull_refresh_load_height'))
                .textAlign(TextAlign.Center)
                .margin({ left: this.newsDataListIndex === NEWS_MAX_LIST && this.isLoading ? 0 : 8 })
                .fontColor(this.refreshConfigurator !== undefined ? this.refreshConfigurator.getLoadTextColor() : 0)
                .fontSize(this.refreshConfigurator !== undefined ? this.refreshConfigurator.getLoadTextSize() : 0)
                .visibility(this.pullHeightValue > CHANGE_PAGE_STATE ? Visibility.Visible : Visibility.Hidden)
          }
       }
       .height($r('app.string.pull_refresh_load_height'))
    }
    
  5. 通过下拉距离判断页面是刷新当前数据还是更新为下一页。源码参考PullToRefreshNews.ets
    onAnimPullDown: (value) => {
       this.pullHeightValue = value;
    },
    onAnimRefreshing: (value, width, height) => {
       if (value !== undefined && width !== undefined && height !== undefined) {
          if (value) {
             this.angle2 = value * 360;
             if (this.pullHeightValue > LOAD_PULL_STATE_CHANGE && this.pullHeightValue <= CHANGE_PAGE_STATE) {
                this.isChangePage = false;
             } else {
                // 当下拉到最顶部时,触发更新页面,不再刷新当前页。
                this.isChangePage = true;
             }
          }
       }
    }
    
  6. 自定义上拉加载动画。源码参考PullToRefreshNews.ets
    @Builder
    private customLoad() {
      Row() {
        Stack() {
          // 上拉1阶段箭头图片
          Image(pull_icon_up)
            .width('100%')
            .height('100%')
            .objectFit(ImageFit.Contain)
            .visibility(this.isPullUp ? Visibility.Visible : Visibility.Hidden)
            .rotate({
              z: 1,
              angle: this.angle1 !== undefined ? this.angle1 : 0
            })
          // 加载时图片
          Image(pull_icon_load)
            .width('100%')
            .height('100%')
            .objectFit(ImageFit.Contain)
            .visibility(this.isLoading ? Visibility.Visible : Visibility.Hidden)
            .rotate({
              z: 1,
              angle: this.angle2 !== undefined ? this.angle2 : 0
            })
        }
        // 最后一页加载时隐藏加载图片
        .width(this.newsDataListIndex === NEWS_MAX_LIST && this.isLoading ? 0 :
        this.refreshConfigurator.getLoadImgHeight())
        .height(this.newsDataListIndex === NEWS_MAX_LIST && this.isLoading ? 0 :
        this.refreshConfigurator.getLoadImgHeight())
    
        // 上拉过程与加载时提示文本
        Text(this.loadText)
          .height('100%')
          .textAlign(TextAlign.Center)
          .margin({ left: this.newsDataListIndex === NEWS_MAX_LIST && this.isLoading ? 0 : 8 })
          .fontColor(this.refreshConfigurator !== undefined ? this.refreshConfigurator.getLoadTextColor() : 0)
          .fontSize(this.refreshConfigurator !== undefined ? this.refreshConfigurator.getLoadTextSize() : 0)
      }
      .height('100%')
    }
    
  7. 设置上拉与加载时的动画回调。源码参考PullToRefreshNews.ets
    onAnimPullUp: (value, width, height) => {
      if (value !== undefined && width !== undefined && height !== undefined) {
        if (value) {
          this.isLoading = false;
          this.isPullUp = true;
          // 判断上拉拖拽过程中高度是否超过阶段临界值
          if (value < LOAD_PULL_STATE_CHANGE) {
            // 归零角度,保持箭头朝上
             this.angle1 = 0;
             // 改变提示文本为上拉1阶段
             this.loadText = LOAD_TEXT_PULL_UP_1;
          } else {
            // 翻转角度,保持箭头朝下
             this.angle1 = 180;
             // 改变提示文本为上拉2阶段
             this.loadText = LOAD_TEXT_PULL_UP_2;
          }
        }
      }
    },
    
    onAnimLoading: (value, width, height) => {
      if (value !== undefined && width !== undefined && height !== undefined) {
        if (value) {
          this.isPullUp = false;
          this.isLoading = true;
          // 更改角度使加载图片保持旋转
          this.angle2 = value * 360;
          // 判读页码是否为最后一页
          if (this.newsDataListIndex !== NEWS_MAX_LIST) {
            this.loadText = LOAD_DEFAULT_TEXT;
          } else {
            // 最后一页更换文本提示已经到底了
            this.loadText = LOAD_STOP_TEXT;
          }
        }
      }
    }
    

高性能知识点

不涉及

工程结构&模块类型

pulltorefreshnews                     // har类型
|---model 
|---|---AppInfo.ets                   // App信息
|---|---UserInformation.ets           // 用户信息    
|---view                              
|---|---PullToRefreshNews.ets         // 视图层-场景列表页面

模块依赖

PullToRefresh

参考资料

PullToRefresh LazyForEach PullToRefresh第三方库

相关权限

不涉及。

依赖

不涉及。

约束与限制

1.本示例仅支持标准系统上运行,支持设备:RK3586。

2.本示例为Stage模型,支持API12版本SDK,SDK版本号(API Version 12 Release)。

3.本示例需要使用DevEco Studio版本号(DevEco Studio 5.0.0 Release)及以上版本才可编译运行。

下载

如需单独下载本工程,执行如下命令:

git init
git config core.sparsecheckout true
echo code/UI/PullToRefresh/ > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openharmony/applications_app_samples.git
git@gitee.com:openharmony/applications_app_samples.git
openharmony
applications_app_samples
applications_app_samples
master

搜索帮助