鸿蒙开发:一个轻盈的上拉下拉刷新组件

ops/2024/12/16 3:08:42/

前言

老早之前开源了一个刷新组件,提供了很多常见的功能,也封装了List,Grid,WaterFlow,虽然功能多,但也冗余比较多,随着时间的前去,暴露的问题就慢慢增多,虽然我也提供了通用的RefrshLayout,奈何很多人仍然有许多问题,但大部分都是相关属性以及用法的问题,对于我来说也比较苦恼,既然如此,那就只封装一个刷新加载,其它的自己实现好了,于是针对refresh的轻盈组件就剥离出来了。

因为它只是一个刷新组件,也仅仅是提供刷新能力,并不提供数据加载服务,这是和refrsh组件的不同之处,当然了,也是灵活之处,毕竟列表的组件是自己写的,需要什么样式更加灵活,但是在代码层次上也稍显冗余,不过有舍就有得。

目前已上传至了中心仓库,地址是:

https://ohpm.openharmony.cn/#/cn/detail/@abner%2Flithe_refresh

刷新库功能效果一览

1、所有功能

2、各个功能效果

快速使用

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

建议:在使用的模块路径下进行执行命令。

ohpm install @abner/lithe_refresh

方式二:在工程的oh-package.json5中设置三方包依赖,配置示例如下:

"dependencies": { "@abner/lithe_refresh": "^1.0.0"}

使用注意

可以使用LitheRefresh组件,包裹想刷新的任意组件,相对比较灵活,如果您想实现懒加载数据模式,建议结合提供的RefreshDataSource,可以让您实现更加方便。

有一点需要知道,如果是包裹的是可滑动组件,比如List,Grid,WaterFlow等,需要配合nestedScroll属性,来解决滑动之间的冲突。

代码案例

1、简单使用

controller: RefreshController = new RefreshController()//任意组件,可以是List、Grid,WaterFlow ……
@BuilderitemLayout() {Column() {}.width("100%").height("100%").backgroundColor(Color.Pink).justifyContent(FlexAlign.Center)}LitheRefresh({itemLayout: this.itemLayout,controller: this.controller,onRefresh: () => {//下拉刷新this.controller.finishRefresh()},onLoadMore: () => {//加载更多this.controller.finishLoadMore()}
})

2、List使用

@Entry
@Component
struct ListUpAndDownPage {@State testArray: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]scroller: Scroller = new Scroller()controller: RefreshController = new RefreshController()@BuilderitemLayout(_this: ListUpAndDownPage) {List({ scroller: _this.scroller, space: 20 }) {ForEach(_this.testArray, (item: number) => {ListItem() {Text('' + item).width('100%').height(80).fontSize(16).textAlign(TextAlign.Center).backgroundColor(0xFFFFFF).border({ width: 2, color: Color.Pink })}}, (item: string, index: number) => JSON.stringify(item) + "_" + index)}.scrollBar(BarState.Off).edgeEffect(EdgeEffect.None).width("100%").height("100%").padding({ left: 20, right: 20 }).nestedScroll({scrollForward: NestedScrollMode.PARENT_FIRST,scrollBackward: NestedScrollMode.PARENT_FIRST})}build() {Column() {LitheRefresh({scroller: this.scroller,controller: this.controller,itemLayout: () => {this.itemLayout(this)},onRefresh: () => {//下拉刷新setTimeout(() => {this.controller.finishRefresh()}, 2000)},onLoadMore: () => {//上拉加载setTimeout(() => {this.testArray.push(13)this.testArray.push(14)this.controller.finishLoadMore()}, 2000)}})}}
}

3、Grid使用

@Entry
@Component
struct GridUpAndDownPage {@State testArray: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]scroller: Scroller = new Scroller()controller: RefreshController = new RefreshController()@BuilderitemLayout(_this: GridUpAndDownPage) {Grid(_this.scroller) {ForEach(_this.testArray, (item: number) => {GridItem() {Text('' + item).width('100%').height(80).fontSize(16).textAlign(TextAlign.Center).backgroundColor(0xFFFFFF).border({ width: 2, color: Color.Pink })}}, (item: string, index: number) => JSON.stringify(item) + "_" + index)}.columnsTemplate("1fr 1fr").columnsGap(10).rowsGap(10).scrollBar(BarState.Off).edgeEffect(EdgeEffect.None).width("100%").height("100%").padding({ left: 20, right: 20 }).nestedScroll({scrollForward: NestedScrollMode.PARENT_FIRST,scrollBackward: NestedScrollMode.PARENT_FIRST})}build() {Column() {ActionBar({title: "Grid组件刷新",barBackgroundColor: Color.Red,leftText: "返回",onLeftClick: () => {router.back()},})LitheRefresh({scroller: this.scroller,controller: this.controller,itemLayout: () => {this.itemLayout(this)},onRefresh: () => {//下拉刷新setTimeout(() => {this.controller.finishRefresh()}, 2000)},onLoadMore: () => {//上拉加载setTimeout(() => {this.testArray.push(13)this.testArray.push(14)this.controller.finishLoadMore()}, 2000)}})}}
}

3、WaterFlow使用

这里没有使用提供RefreshDataSource,所以懒加载方式比较冗余,为了简洁代码,建议使用我提供的RefreshDataSource,可以让您的效率极大提升。

具体RefreshDataSource使用方式,可以查看Demo中LazyDataOperationPage页面。

@Entry@Componentstruct WaterFlowUpAndDownPage {scroller: Scroller = new Scroller()controller: RefreshController = new RefreshController()@BuilderitemLayout(_this: WaterFlowUpAndDownPage) {WaterFlowView({scroller: _this.scroller})}build() {Column() {LitheRefresh({scroller: this.scroller,controller: this.controller,itemLayout: () => {this.itemLayout(this)},onRefresh: () => {//下拉刷新setTimeout(() => {this.controller.finishRefresh()}, 2000)},onLoadMore: () => {//上拉加载setTimeout(() => {this.controller.finishLoadMore()}, 2000)}})}}}@Componentstruct WaterFlowView {@State minSize: number = 80@State maxSize: number = 180@State fontSize: number = 24@State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]scroller: Scroller = new Scroller()dataSource: WaterFlowDataSource = new WaterFlowDataSource()private itemWidthArray: number[] = []private itemHeightArray: number[] = []// 计算FlowItem宽/高getSize() {let ret = Math.floor(Math.random() * this.maxSize)return (ret > this.minSize ? ret : this.minSize)}// 设置FlowItem的宽/高数组setItemSizeArray() {for (let i = 0; i < 30; i++) {this.itemWidthArray.push(this.getSize())this.itemHeightArray.push(this.getSize())}}aboutToAppear() {this.setItemSizeArray()}build() {WaterFlow({ scroller: this.scroller }) {LazyForEach(this.dataSource, (item: number) => {FlowItem() {Column() {Text("N" + item).fontSize(12).height('16')}}.width('100%').height(this.itemHeightArray[item % 30]).backgroundColor(this.colors[item % 5])}, (item: string) => item)}.columnsTemplate("1fr 1fr").columnsGap(10).rowsGap(5).backgroundColor(0xFAEEE0).width('100%').height('100%').nestedScroll({scrollForward: NestedScrollMode.PARENT_FIRST,scrollBackward: NestedScrollMode.PARENT_FIRST})}}// 实现IDataSource接口的对象,用于瀑布流组件加载数据
export class WaterFlowDataSource implements IDataSource {private dataArray: number[] = []private listeners: DataChangeListener[] = []constructor() {for (let i = 0; i < 30; i++) {this.dataArray.push(i)}}// 获取索引对应的数据public getData(index: number): number {return this.dataArray[index]}// 通知控制器数据重新加载notifyDataReload(): void {this.listeners.forEach(listener => {listener.onDataReloaded()})}// 通知控制器数据增加notifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDataAdd(index)})}// 通知控制器数据变化notifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDataChange(index)})}// 通知控制器数据删除notifyDataDelete(index: number): void {this.listeners.forEach(listener => {listener.onDataDelete(index)})}// 通知控制器数据位置变化notifyDataMove(from: number, to: number): void {this.listeners.forEach(listener => {listener.onDataMove(from, to)})}//通知控制器数据批量修改notifyDatasetChange(operations: DataOperation[]): void {this.listeners.forEach(listener => {listener.onDatasetChange(operations);})}// 获取数据总数public totalCount(): number {return this.dataArray.length}// 注册改变数据的控制器registerDataChangeListener(listener: DataChangeListener): void {if (this.listeners.indexOf(listener) < 0) {this.listeners.push(listener)}}// 注销改变数据的控制器unregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener)if (pos >= 0) {this.listeners.splice(pos, 1)}}// 增加数据public add1stItem(): void {this.dataArray.splice(0, 0, this.dataArray.length)this.notifyDataAdd(0)}// 在数据尾部增加一个元素public addLastItem(): void {this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length)this.notifyDataAdd(this.dataArray.length - 1)}// 在指定索引位置增加一个元素public addItem(index: number): void {this.dataArray.splice(index, 0, this.dataArray.length)this.notifyDataAdd(index)}// 删除第一个元素public delete1stItem(): void {this.dataArray.splice(0, 1)this.notifyDataDelete(0)}// 删除第二个元素public delete2ndItem(): void {this.dataArray.splice(1, 1)this.notifyDataDelete(1)}// 删除最后一个元素public deleteLastItem(): void {this.dataArray.splice(-1, 1)this.notifyDataDelete(this.dataArray.length)}// 在指定索引位置删除一个元素public deleteItem(index: number): void {this.dataArray.splice(index, 1)this.notifyDataDelete(index)}// 重新加载数据public reload(): void {this.dataArray.splice(1, 1)this.dataArray.splice(3, 2)this.notifyDataReload()}
}

使用总结

在和可滑动组件使用的时候,记得一定要和nestedScroll属性配合使用,用于解决滑动冲突,除此之外,还需要传递滑动组件的scroller属性,用于手势操作。


http://www.ppmy.cn/ops/142272.html

相关文章

Android Studio更改项目使用的JDK

一、吐槽 过去&#xff0c;在安卓项目中配置JDK和Gradle的过程非常直观&#xff0c;只需要进入Android Studio的File菜单中的Project Structure即可进行设置&#xff0c;十分方便。 原本可以在这修改JDK: 但大家都知道&#xff0c;Android Studio的狗屎性能&#xff0c;再加…

服务器数据恢复—热备盘上线过程中硬盘离线导致raid5阵列崩溃的数据恢复案例

服务器数据恢复环境&#xff1a; 两组分别由4块SAS接口硬盘组建的raid5阵列&#xff0c;两组raid5阵列划分LUN并由LVM管理&#xff0c;格式化为EXT3文件系统。 服务器故障&#xff1a; RAID5阵列中一块硬盘未知原因离线&#xff0c;热备盘自动激活上线替换离线硬盘。在热备盘上…

防范TCP攻击:策略与实践

TCP&#xff08;传输控制协议&#xff09;是互联网通信的核心协议之一&#xff0c;它确保了数据在网络上的可靠传输。然而&#xff0c;TCP也容易成为各种网络攻击的目标&#xff0c;如SYN洪水攻击、TCP连接耗尽攻击等。本文将探讨如何通过配置防火墙规则、优化服务器设置以及采…

docker 发布 net5 教程

基于已经打包好程序 1. 在/home/ 建立目录 cd /home/ mkdir netcore2.把已打包好项目文件上传到该目录 3.创建 Dockerfile cd netcore vi Dockerfile 4. 写入以下内容到Dockerfile #注意 COPY . /app 之间都有空格 # EXPOSE xxx 暴露端口 FROM mcr.microsoft.com/dotn…

评估一套呼叫中心大模型呼入机器人的投入回报比?

评估一套呼叫中心大模型呼入机器人的投入回报比&#xff1f; 原作者&#xff1a;开源呼叫中心FreeIPCC&#xff0c;其Github&#xff1a;https://github.com/lihaiya/freeipcc 评估一套呼叫中心大模型呼入机器人的投入回报比&#xff08;ROI&#xff09;&#xff0c;是一个多…

川渝地区软件工程考研择校分析

通过最新数据分析,5所高校软件工程专业2025年考研难度从高到低预计为: 电子科技大学 >> 四川大学 > 重庆大学 ≈ 西南交通大学 > 西南大学 对于想考川渝地区985但核心目标为优先上岸的考生,建议重点考虑西南交通大学软件工程学硕。该校24届软件工程学硕实际录取1…

【Unity踩坑】Unity生成iOS的XCode项目时提示错误:xcrun: error: SDK “iphoneos“ cannot be located

问题描述&#xff1a; Unity生成iOS的Xcode项目时&#xff0c;出现错误&#xff1a;xcrun: error: SDK “iphoneos” cannot be located 解决方法&#xff1a; 运行Xcode, 打开设置-Locations&#xff0c;将Command Line Tools里下拉项再选择一下。&#xff08;不管之前有没有…

3D 生成重建037-GAUSSIANANYTHING通过点云与外观的混合策略进行3dgs生成

3D 生成重建037-GAUSSIANANYTHING通过点云与外观的混合策略进行3dgs生成 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 虽然现有的三维内容生成方法取得了显著进展&#xff0c;但它们在生成高质量、易编辑且可控的三维模型方面仍然面临着挑战。现有的方法通常依赖于代…