自学内容网 自学内容网

鸿蒙--下拉刷新+上拉加载

概述

Refresh组件支持下拉刷新,包裹list组件,下拉事件中更新列表

这里我们需要提前了解一下 @Builder装饰器 的基本用法

ArkUI提供了一种轻量的UI元素复用机制@Builder,该自定义组件内部UI结构固定,仅与使用方进行数据传递,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。

具体用法可参考官网文档:文档中心

在后面我们也会去详细的讲解 @Builder装饰器 的使用

对于滚动有List和Scroll,List适合数量不确定的滚动,比如评论列表等;Scroll适合数量确定的滚动

上拉刷新

这里主要用到 Refresh组件 的 onRefreshing 函数

@Entry
@Component
struct Index {
  // 是否需要刷新
  @State
  refreshing: boolean = false

  // 自定义构建函数--给组件传递
  @Builder
  refreshContent() {
    // Text('正在玩命加载中...')
    //   .width('100%')
    //   .textAlign(TextAlign.Center)
    //   .backgroundColor(Color.Pink)
    Row({space: 8}) {
      LoadingProgress()
        .height(24)
      Text('正在玩命加载中...')
    }
    .width('100%')
    .padding(12)
    .justifyContent(FlexAlign.Center)
  }

  // 定义随机数据
  @State
  list: number[] = Array(20).fill(Date.now())

  // 下拉加载用到
  scroller:Scroller = new Scroller()
  @State
  isEnd: boolean = false

  build() {
    RelativeContainer() {
      // Refresh 刷新组件
      // 参数说明:refreshing 组件当前是否处于刷新中状态;builder 自定义刷新区域显示内容(结构体),参数可选
      Refresh({refreshing: $$this.refreshing, builder: this.refreshContent}) {
        List() {
          ForEach(this.list, (item: number) => {
            ListItem() {
              Row() {
                Text(item.toString())
                  .width('100%')
                  .padding(20)
                  .border({
                    width: {
                      bottom: 1
                    },
                    style: {
                      bottom: BorderStyle.Dashed
                    },
                    color: Color.Gray
                  })
              }
            }
          })
        }
      }
      // 监听是否刷新完毕(真正的刷新操作)-从而进行数据更新操作
      .onRefreshing(() => {
        setTimeout(() => {
          // 更新数据
          this.list = Array(20).fill(Date.now())
          // 手动关闭刷新状态
          this.refreshing = false
        }, 1000)
      })
    }
    .width('100%')
    .height('100%')
  }
}

 

下拉加载

注册三个事件,开始滚动,滚动结束,滚动至列表尾部(触发两次,滚动至+回弹)

设置变量是否滚动底部,开始滚动false,滚动至列表尾部true,滚动结束判断变量进行数据追加

触底了--只有触底了才会进行数据加载,这里会出现加载两次的情况,因此在这里不适合进行数据的请求操作

对于数据的请求我们需要利用 onScrollStart 和 onScrollStop 和 onReachEnd 三个进行联合判断,从而进行数据请求操作

数据请求逻辑:1.开始滚动,更新状态为没有触底不进行数据加载;2.停止滚动,是否触底了触底了才加载数据,反之不加载数据;3.触底,记录触底了

下拉加载数据完成了应该让滚动条滚动到底部去,不然不知道是否已经加载成功了

import { promptAction } from '@kit.ArkUI'
import HmLoading from './components/HmLoading'

@Entry
@Component
struct Index {
  // 是否需要刷新
  @State
  refreshing: boolean = false

  // 自定义构建函数--给组件传递
  @Builder
  refreshContent() {
    // Text('正在玩命加载中...')
    //   .width('100%')
    //   .textAlign(TextAlign.Center)
    //   .backgroundColor(Color.Pink)
    Row({space: 8}) {
      LoadingProgress()
        .height(24)
      Text('正在玩命加载中...')
    }
    .width('100%')
    .padding(12)
    .justifyContent(FlexAlign.Center)
  }

  // 定义随机数据
  @State
  list: number[] = Array(20).fill(Date.now())

  // 下拉加载用到:用于下拉加载成功后让滚动条滚动到底部自动
  scroller:Scroller = new Scroller()

  @State
  isEnd: boolean = false

  @State
  isLoading: boolean = false

  total:number = 43

  build() {
    Stack() {
      RelativeContainer() {
        // Refresh 刷新组件
        // 参数说明:refreshing 组件当前是否处于刷新中状态;builder 自定义刷新区域显示内容(结构体),参数可选
        Refresh({refreshing: $$this.refreshing, builder: this.refreshContent}) {
          List({scroller: this.scroller}) {
            ForEach(this.list, (item: number) => {
              ListItem() {
                Row() {
                  Text(item.toString())
                    .width('100%')
                    .padding(20)
                    .border({
                      width: {
                        bottom: 1
                      },
                      style: {
                        bottom: BorderStyle.Dashed
                      },
                      color: Color.Gray
                    })
                }
              }
            })
            if(this.list.length > this.total) {
              ListItem() {
                Row() {
                  Text('我是有底线的~')
                }
                .width('100%')
                .padding(12)
                .justifyContent(FlexAlign.Center)
              }
            }
          }
          // 开始滚动
          .onScrollStart(() => {
            promptAction.showToast({
              message: '开始滚动'
            })
            this.isEnd = false;
          })
          // 停止滚动
          .onScrollStop(() => {
            // 节流效果
            if(this.isLoading || this.list.length > this.total) return;

            promptAction.showToast({
              message: '停止滚动'
            })
            if(this.isEnd) {
              this.isLoading = true;
              // 数据加载
              setTimeout(() => {
                const list:number[] = Array(10).fill(Math.random())
                this.list.push(...list)
                this.scroller.scrollEdge(Edge.Bottom)
                this.isLoading = false;
              }, 1000)
            }
          })
          // 触底了--只有触底了才会进行数据加载,这里会出现加载两次的情况,因此在这里不适合进行数据的请求操作
          // 对于数据的请求我们需要利用 onScrollStart 和 onScrollStop 和 onReachEnd 三个进行联合判断,从而进行数据请求操作
          // 数据请求逻辑:1.开始滚动,更新状态为没有触底不进行数据加载;2.停止滚动,是否触底了触底了才加载数据,反之不加载数据;3.触底,记录触底了
          .onReachEnd(() => {
            promptAction.showToast({
              message: '触底了'
            })
            this.isEnd = true;
          })
        }
        // 监听是否刷新完毕(真正的刷新操作)-从而进行数据更新操作
        .onRefreshing(() => {
          setTimeout(() => {
            // 更新数据
            this.list = Array(20).fill(Date.now())
            // 手动关闭刷新状态
            this.refreshing = false
          }, 1000)
        })
      }
      .width('100%')
      .height('100%')

      if(this.isLoading) {
        Column() {
          HmLoading()
        }
        .height('100%')
        .width('100%')
        .backgroundColor('#ba0a0000')
        .justifyContent(FlexAlign.Center)
      }
    }
  }
}

 


原文地址:https://blog.csdn.net/weixin_43285360/article/details/142812204

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!