ArkUI实战,自定义下拉刷新组件RefreshList

下拉刷新是一个高频使用的功能,ArkUI 开发框架也提供了下拉刷新组件 Refresh,该组件的使用非常简单,读者可参阅笔者在《ArkUI实战》第六章 第 5 小节 的介绍,本文笔者讲解一下笔者在项目上实现的一个下拉刷新组件 RefreshList,该组件的运行效果如下图所示:
在这里插入图片描述

  • 布局拆分
    下拉刷新组件都是分为上下两部分,上边是刷新头:refreshHead,该刷新头根据手指的下滑距离提示是否达到刷新条件;下边是刷新体:refreshContent,当触发下拉刷新条件后对外回调,从而实现内容更新。笔者实现的 RefreshList 也是按照以上布局实现的,简化图如下所示:
    在这里插入图片描述
    默认情况下 refreshHead 是布局在 RefreshList 可视区域外边,笔者在第三章 第 1 小节 讲解过可以使用 position() 方法实现布局定位,简化代码如下所示:
@Component struct RefreshList {
   
  build() {
   
    Column() {
   
      Row() {
   
        // header布局
      }
      .id("refresh_header")
      .width("100%")
      .height(50)
      .position({
    // 利用该属性,把refresh_header布局在 Column 顶部
        x: 0,
        y: -50
      })

      Column() {
   
        // content 布局
      }
      .id("refresh_content")
      .width("100%")
      .height("100%")
      .position({
    // 利用该属性,把refresh_content布局向上做偏移
        x: 0,
        y: 0
      })
    }
    .id("refresh_list")
    .width("100%")
    .height("100%")
  }
}
  • 滑动处理
    ArkUI 开发框架对于手势事件的处理遵循 W3C 标准,首先是目标捕获阶段,然后再是事件冒泡阶段,下拉刷新的操作就是在事件冒泡阶段处理的,因此直接实现 refresh_list 的 onTouch() 方法即可,在该方法内根据手指的滑动距离动态实现 refreshHeader 和 refreshContent 的布局定位即可,简化代码如下所示:
@Component struct RefreshList {
   

  private refreshHeaderHeight: number = 50;
  private offsetY: number = -this.refreshHeaderHeight;
  private lastX: number;
  private lastY: number;
  private downY: number;

  build() {
   
    Column() {
   
      Row()
      .id("refresh_header")
      .width("100%")
      .height(this.refreshHeaderHeight)
      .backgroundColor("#bbaacc")
      .position({
   
        x: 0,
        y: this.offsetY
      })

      Column() {
   
      }
      .id("refresh_content")
      .width("100%")
      .height("100%")
      .backgroundColor("#aabbcc")
      .position({
   
        x: 0,
        y: this.offsetY + this.refreshHeaderHeight
      })
    }
    .id("refresh_list")
    .width("100%")
    .height("100%")
    .onTouch((event) => {
   
      if (event.type == TouchType.Down) {
   
        // 处理 down 事件
        this.onTouchDown(event);
      } else if (event.type == TouchType.Move) {
   
        // 处理 move 事件
        this.onTouchMove(event);
      } else if (event.type == TouchType.Cancel || event.type == TouchType.Up) {
   
        // 处理 up 事件
        this.onTouchUp(event);
      }
    })
  }

  private onTouchDown(event: TouchEvent) {
   
    this.lastX = event.touches[0].screenX;
    this.lastY = event.touches[0].screenY;
    this.downY = this.lastY;
  }

  private onTouchMove(event: TouchEvent) {
   
    let currentX = event.touches[0].screenX;
    let currentY = event.touches[0].screenY;
    let deltaX = currentX - this.lastX;
    let deltaY = currentY - this.lastY;

    if (Math.abs(deltaX) < Math.abs(deltaY) && Math.abs(deltaY) > 5) {
   
      // 达到滑动条件
    }
  }

  private onTouchUp(event: TouchEvent) {
   
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个示例的uniapp下拉刷新组件代码: ```html <template> <view> <view class="refresh-text">{{refreshText}}</view> <scroll-view :style="{height:scrollViewHeight + 'px'}" scroll-y="true" @scrolltoupper="onScrollToUpper" @scroll="onScroll"> <view class="list"> <view class="list-item" v-for="(item, index) in list" :key="index"> {{item}} </view> </view> </scroll-view> </view> </template> <script> export default { data() { return { list: [], // 数据列表 page: 1, // 当前页码 isLoading: false, // 是否正在加载数据 refreshText: '下拉刷新', // 刷新文本 startScrollTop: 0, // 滚动条开始位置 scrollViewHeight: 0, // 滚动区域高度 }; }, methods: { // 下拉刷新 onScrollToUpper() { if (this.isLoading) { return; } this.isLoading = true; this.refreshText = '正在刷新...'; // 模拟加载数据 setTimeout(() => { this.list = ['刷新数据1', '刷新数据2', '刷新数据3']; this.page = 1; this.isLoading = false; this.refreshText = '下拉刷新'; }, 2000); }, // 滚动事件 onScroll(e) { if (this.isLoading) { return; } const scrollTop = e.detail.scrollTop; const scrollViewHeight = e.detail.scrollHeight; const windowHeight = uni.getSystemInfoSync().windowHeight; if (scrollTop < this.startScrollTop && scrollTop <= 0) { // 向上滚动并且滚动到顶部,触发下拉刷新 this.onScrollToUpper(); } else if (scrollViewHeight - (scrollTop + windowHeight) <= 10) { // 滚动到底部,触发加载更多 this.onLoadMore(); } this.startScrollTop = scrollTop; this.scrollViewHeight = scrollViewHeight; }, // 加载更多 onLoadMore() { if (this.isLoading) { return; } this.isLoading = true; // 模拟加载数据 setTimeout(() => { this.list = [...this.list, `加载更多数据${this.page + 1}`, `加载更多数据${this.page + 2}`, `加载更多数据${this.page + 3}`]; this.page++; this.isLoading = false; }, 2000); }, }, }; </script> ``` 这个示例包含一个下拉刷新组件和一个滚动加载更多组件,可以在下拉到顶部时触发下拉刷新,滚动到底部时触发加载更多。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值