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

[复制链接]
发表于 2024-12-15 18:33:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
媒介


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

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

现在已上传至了中央仓库,地址是:
https://ohpm.openharmony.cn/#/cn/detail/@abner%2Flithe_refresh

革新库功能结果一览


1、所有功能





2、各个功能结果





快速利用


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

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

  1. ohpm install @abner/lithe_refresh
复制代码

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

  1. "dependencies": { "@abner/lithe_refresh": "^1.0.0"}
复制代码

利用留意


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

有一点须要知道,如果是包裹的是可滑动组件,比如List,Grid,WaterFlow等,须要配合nestedScroll属性,来办理滑动之间的辩说。

代码案例


1、简单利用


  1. controller: RefreshController = new RefreshController()
  2. //任意组件,可以是List、Grid,WaterFlow ……
  3. @Builder
  4.   itemLayout() {
  5.     Column() {
  6.     }.width("100%")
  7.       .height("100%")
  8.       .backgroundColor(Color.Pink)
  9.       .justifyContent(FlexAlign.Center)
  10.   }
  11. LitheRefresh({
  12.   itemLayout: this.itemLayout,
  13.   controller: this.controller,
  14.   onRefresh: () => {
  15.     //下拉刷新
  16.     this.controller.finishRefresh()
  17.   },
  18.   onLoadMore: () => {
  19.     //加载更多
  20.     this.controller.finishLoadMore()
  21.   }
  22. })
复制代码
2、List利用


  1. @Entry
  2. @Component
  3. struct ListUpAndDownPage {
  4.   @State testArray: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  5.   scroller: Scroller = new Scroller()
  6.   controller: RefreshController = new RefreshController()
  7.   @Builder
  8.   itemLayout(_this: ListUpAndDownPage) {
  9.     List({ scroller: _this.scroller, space: 20 }) {
  10.       ForEach(_this.testArray, (item: number) => {
  11.         ListItem() {
  12.           Text('' + item)
  13.             .width('100%')
  14.             .height(80)
  15.             .fontSize(16)
  16.             .textAlign(TextAlign.Center)
  17.             .backgroundColor(0xFFFFFF)
  18.             .border({ width: 2, color: Color.Pink })
  19.         }
  20.       }, (item: string, index: number) => JSON.stringify(item) + "_" + index)
  21.     }
  22.     .scrollBar(BarState.Off)
  23.     .edgeEffect(EdgeEffect.None)
  24.     .width("100%")
  25.     .height("100%")
  26.     .padding({ left: 20, right: 20 })
  27.     .nestedScroll({
  28.       scrollForward: NestedScrollMode.PARENT_FIRST,
  29.       scrollBackward: NestedScrollMode.PARENT_FIRST
  30.     })
  31.   }
  32.   build() {
  33.     Column() {
  34.       
  35.       LitheRefresh({
  36.         scroller: this.scroller,
  37.         controller: this.controller,
  38.         itemLayout: () => {
  39.           this.itemLayout(this)
  40.         },
  41.         onRefresh: () => {
  42.           //下拉刷新
  43.           setTimeout(() => {
  44.             this.controller.finishRefresh()
  45.           }, 2000)
  46.         },
  47.         onLoadMore: () => {
  48.           //上拉加载
  49.           setTimeout(() => {
  50.             this.testArray.push(13)
  51.             this.testArray.push(14)
  52.             this.controller.finishLoadMore()
  53.           }, 2000)
  54.         }
  55.       })
  56.     }
  57.   }
  58. }
复制代码

3、Grid利用


  1. @Entry
  2. @Component
  3. struct GridUpAndDownPage {
  4.   @State testArray: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  5.   scroller: Scroller = new Scroller()
  6.   controller: RefreshController = new RefreshController()
  7.   @Builder
  8.   itemLayout(_this: GridUpAndDownPage) {
  9.     Grid(_this.scroller) {
  10.       ForEach(_this.testArray, (item: number) => {
  11.         GridItem() {
  12.           Text('' + item)
  13.             .width('100%')
  14.             .height(80)
  15.             .fontSize(16)
  16.             .textAlign(TextAlign.Center)
  17.             .backgroundColor(0xFFFFFF)
  18.             .border({ width: 2, color: Color.Pink })
  19.         }
  20.       }, (item: string, index: number) => JSON.stringify(item) + "_" + index)
  21.     }
  22.     .columnsTemplate("1fr 1fr")
  23.     .columnsGap(10)
  24.     .rowsGap(10)
  25.     .scrollBar(BarState.Off)
  26.     .edgeEffect(EdgeEffect.None)
  27.     .width("100%")
  28.     .height("100%")
  29.     .padding({ left: 20, right: 20 })
  30.     .nestedScroll({
  31.       scrollForward: NestedScrollMode.PARENT_FIRST,
  32.       scrollBackward: NestedScrollMode.PARENT_FIRST
  33.     })
  34.   }
  35.   build() {
  36.     Column() {
  37.       ActionBar({
  38.         title: "Grid组件刷新",
  39.         barBackgroundColor: Color.Red,
  40.         leftText: "返回",
  41.         onLeftClick: () => {
  42.           router.back()
  43.         },
  44.       })
  45.       LitheRefresh({
  46.         scroller: this.scroller,
  47.         controller: this.controller,
  48.         itemLayout: () => {
  49.           this.itemLayout(this)
  50.         },
  51.         onRefresh: () => {
  52.           //下拉刷新
  53.           setTimeout(() => {
  54.             this.controller.finishRefresh()
  55.           }, 2000)
  56.         },
  57.         onLoadMore: () => {
  58.           //上拉加载
  59.           setTimeout(() => {
  60.             this.testArray.push(13)
  61.             this.testArray.push(14)
  62.             this.controller.finishLoadMore()
  63.           }, 2000)
  64.         }
  65.       })
  66.     }
  67.   }
  68. }
复制代码

3、WaterFlow利用


这里没有利用提供RefreshDataSource,以是懒加载方式比较冗余,为了简便代码,建议利用我提供的RefreshDataSource,可以让您的服从极大提升。

详细RefreshDataSource利用方式,可以查看Demo中LazyDataOperationPage页面。

  1. @Entry
  2.   @Component
  3.   struct WaterFlowUpAndDownPage {
  4.     scroller: Scroller = new Scroller()
  5.     controller: RefreshController = new RefreshController()
  6.     @Builder
  7.     itemLayout(_this: WaterFlowUpAndDownPage) {
  8.       WaterFlowView({
  9.         scroller: _this.scroller
  10.       })
  11.     }
  12.     build() {
  13.       Column() {
  14.         LitheRefresh({
  15.           scroller: this.scroller,
  16.           controller: this.controller,
  17.           itemLayout: () => {
  18.             this.itemLayout(this)
  19.           },
  20.           onRefresh: () => {
  21.             //下拉刷新
  22.             setTimeout(() => {
  23.               this.controller.finishRefresh()
  24.             }, 2000)
  25.           },
  26.           onLoadMore: () => {
  27.             //上拉加载
  28.             setTimeout(() => {
  29.               this.controller.finishLoadMore()
  30.             }, 2000)
  31.           }
  32.         })
  33.       }
  34.     }
  35.   }
  36. @Component
  37.   struct WaterFlowView {
  38.     @State minSize: number = 80
  39.     @State maxSize: number = 180
  40.     @State fontSize: number = 24
  41.     @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
  42.     scroller: Scroller = new Scroller()
  43.     dataSource: WaterFlowDataSource = new WaterFlowDataSource()
  44.     private itemWidthArray: number[] = []
  45.     private itemHeightArray: number[] = []
  46.     // 计算FlowItem宽/高
  47.     getSize() {
  48.       let ret = Math.floor(Math.random() * this.maxSize)
  49.       return (ret > this.minSize ? ret : this.minSize)
  50.     }
  51.     // 设置FlowItem的宽/高数组
  52.     setItemSizeArray() {
  53.       for (let i = 0; i < 30; i++) {
  54.         this.itemWidthArray.push(this.getSize())
  55.         this.itemHeightArray.push(this.getSize())
  56.       }
  57.     }
  58.     aboutToAppear() {
  59.       this.setItemSizeArray()
  60.     }
  61.     build() {
  62.       WaterFlow({ scroller: this.scroller }) {
  63.         LazyForEach(this.dataSource, (item: number) => {
  64.           FlowItem() {
  65.             Column() {
  66.               Text("N" + item).fontSize(12).height('16')
  67.             }
  68.           }
  69.           .width('100%')
  70.                     .height(this.itemHeightArray[item % 30])
  71.                     .backgroundColor(this.colors[item % 5])
  72.                     }, (item: string) => item)
  73.       }
  74.       .columnsTemplate("1fr 1fr")
  75.         .columnsGap(10)
  76.         .rowsGap(5)
  77.         .backgroundColor(0xFAEEE0)
  78.         .width('100%')
  79.         .height('100%')
  80.         .nestedScroll({
  81.           scrollForward: NestedScrollMode.PARENT_FIRST,
  82.           scrollBackward: NestedScrollMode.PARENT_FIRST
  83.         })
  84.     }
  85.   }
  86. // 实现IDataSource接口的对象,用于瀑布流组件加载数据
  87. export class WaterFlowDataSource implements IDataSource {
  88.   private dataArray: number[] = []
  89.   private listeners: DataChangeListener[] = []
  90.   constructor() {
  91.     for (let i = 0; i < 30; i++) {
  92.       this.dataArray.push(i)
  93.     }
  94.   }
  95.   // 获取索引对应的数据
  96.   public getData(index: number): number {
  97.     return this.dataArray[index]
  98.   }
  99.   // 通知控制器数据重新加载
  100.   notifyDataReload(): void {
  101.     this.listeners.forEach(listener => {
  102.       listener.onDataReloaded()
  103.     })
  104.   }
  105.   // 通知控制器数据增加
  106.   notifyDataAdd(index: number): void {
  107.     this.listeners.forEach(listener => {
  108.       listener.onDataAdd(index)
  109.     })
  110.   }
  111.   // 通知控制器数据变化
  112.   notifyDataChange(index: number): void {
  113.     this.listeners.forEach(listener => {
  114.       listener.onDataChange(index)
  115.     })
  116.   }
  117.   // 通知控制器数据删除
  118.   notifyDataDelete(index: number): void {
  119.     this.listeners.forEach(listener => {
  120.       listener.onDataDelete(index)
  121.     })
  122.   }
  123.   // 通知控制器数据位置变化
  124.   notifyDataMove(from: number, to: number): void {
  125.     this.listeners.forEach(listener => {
  126.       listener.onDataMove(from, to)
  127.     })
  128.   }
  129.   //通知控制器数据批量修改
  130.   notifyDatasetChange(operations: DataOperation[]): void {
  131.     this.listeners.forEach(listener => {
  132.       listener.onDatasetChange(operations);
  133.     })
  134.   }
  135.   // 获取数据总数
  136.   public totalCount(): number {
  137.     return this.dataArray.length
  138.   }
  139.   // 注册改变数据的控制器
  140.   registerDataChangeListener(listener: DataChangeListener): void {
  141.     if (this.listeners.indexOf(listener) < 0) {
  142.       this.listeners.push(listener)
  143.     }
  144.   }
  145.   // 注销改变数据的控制器
  146.   unregisterDataChangeListener(listener: DataChangeListener): void {
  147.     const pos = this.listeners.indexOf(listener)
  148.     if (pos >= 0) {
  149.       this.listeners.splice(pos, 1)
  150.     }
  151.   }
  152.   // 增加数据
  153.   public add1stItem(): void {
  154.     this.dataArray.splice(0, 0, this.dataArray.length)
  155.     this.notifyDataAdd(0)
  156.   }
  157.   // 在数据尾部增加一个元素
  158.   public addLastItem(): void {
  159.     this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length)
  160.     this.notifyDataAdd(this.dataArray.length - 1)
  161.   }
  162.   // 在指定索引位置增加一个元素
  163.   public addItem(index: number): void {
  164.     this.dataArray.splice(index, 0, this.dataArray.length)
  165.     this.notifyDataAdd(index)
  166.   }
  167.   // 删除第一个元素
  168.   public delete1stItem(): void {
  169.     this.dataArray.splice(0, 1)
  170.     this.notifyDataDelete(0)
  171.   }
  172.   // 删除第二个元素
  173.   public delete2ndItem(): void {
  174.     this.dataArray.splice(1, 1)
  175.     this.notifyDataDelete(1)
  176.   }
  177.   // 删除最后一个元素
  178.   public deleteLastItem(): void {
  179.     this.dataArray.splice(-1, 1)
  180.     this.notifyDataDelete(this.dataArray.length)
  181.   }
  182.   // 在指定索引位置删除一个元素
  183.   public deleteItem(index: number): void {
  184.     this.dataArray.splice(index, 1)
  185.     this.notifyDataDelete(index)
  186.   }
  187.   // 重新加载数据
  188.   public reload(): void {
  189.     this.dataArray.splice(1, 1)
  190.     this.dataArray.splice(3, 2)
  191.     this.notifyDataReload()
  192.   }
  193. }
复制代码

利用总结


在和可滑动组件利用的时候,记得肯定要和nestedScroll属性配合利用,用于办理滑动辩说,除此之外,还须要转达滑动组件的scroller属性,用于手势操作。

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表