HarmonyOS引导页登陆页以及tabbar的代码说明 home 下拉刷新页代码 5

news2024/12/28 17:58:05

下拉刷新页

在这里插入图片描述

代码说明

这一页第一次运行时很卡,就是你点击修改,要等一会才出来,加一句,修改的字样原来应是修车二字。只能将错就错。

const TopHeight = 200;
@Component
export default struct Car {
  @State list: Array<number> = []
  // 列表y坐标偏移量
  @State offsetY: number = 0
  // 按下的y坐标
  private downY = 0
  // 上一次移动的y坐标
  private lastMoveY = 0
  // 当前列表首部的索引
  private startIndex = 0
  // 当前列表尾部的索引
  private endIndex = 0

  // 下拉刷新的布局高度
  private pullRefreshHeight = 70
  // 下拉刷新文字:下拉刷新、松开刷新、正在刷新、刷新成功
  @State pullRefreshText: string= '下拉刷新'
  // 下拉刷新图标:与文字对应
  @State pullRefreshImage: Resource = $r("app.media.pullrefresh")
  // 是否可以刷新:未达到刷新条件,收缩回去
  private isCanRefresh = false
  // 是否正在刷新:刷新中不进入触摸逻辑
  private isRefreshing: boolean = false
  // 是否已经进入了下拉刷新操作
  private isPullRefreshOperation = false

  // 上拉加载的布局默认高度
  private loadMoreHeight = 70
  // 上拉加载的布局是否显示
  @State isVisibleLoadMore: boolean = false
  // 是否可以加载更多
  private isCanLoadMore = false
  // 是否加载中:加载中不进入触摸逻辑
  private isLoading: boolean = false


  // 自定义下拉刷新布局
  @Builder CustomPullRefreshLayout(){
    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
      Image(this.pullRefreshImage)
        .width(18)
        .height(18)

      Text(this.pullRefreshText)
        .margin({ left: 7, bottom: 1 })
        .fontSize(17)
    }
    .width('100%')
    .height(this.pullRefreshHeight)
    // 布局跟着列表偏移量移动
    .offset({ x: 0, y: `${vp2px(-this.pullRefreshHeight) + this.offsetY}px` })
  }

  // 自定义加载更多布局
  @Builder CustomLoadMoreLayout(){
    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
      Image($r("app.media.refreshing"))
        .width(18)
        .height(18)

      Text('加载更多中...')
        .margin({ left: 7, bottom: 1 })
        .fontSize(17)
    }
    .width('100%')
    .height(this.loadMoreHeight)
    .backgroundColor('#f4f4f4')
    .visibility(this.isVisibleLoadMore ? Visibility.Visible : Visibility.None)
  }

  // 刷新测试数据
  private refreshData(){
    this.list = []
    for (var i = 0; i < 15; i++) {
      this.list.push(i)
    }
  }

  // 加载更多测试数据
  private loadMoreData(){
    let initValue = this.list[this.list.length-1] + 1
    for (var i = initValue; i < initValue + 10; i++) {
      this.list.push(i)
    }
  }

  build() {
    Column() {
      // 下拉刷新布局
      this.CustomPullRefreshLayout()
      // 列表布局
      List() {
        ForEach(this.list, item => {
          ListItem() {
            Column() {
              Text(`Item ${item}`)
                .padding(15)
                .fontSize(18)
            }
          }
        }, item => item.toString())
        // 加载更多布局
        ListItem(){
          this.CustomLoadMoreLayout()
        }
      }
      .backgroundColor(Color.White) // 背景
      .divider({ color: '#e2e2e2', strokeWidth: 1 }) // 分割线
      .edgeEffect(EdgeEffect.None) // 去掉回弹效果
      .offset({ x: 0, y: `${this.offsetY - TopHeight}px` }) // touch事件计算的偏移量单位是px,记得加上单位
      .onScrollIndex((start, end) => { // 监听当前列表首位索引
        console.info(`${start}=start============end=${end}`)
        this.startIndex = start
        this.endIndex = end
      })

    }
    .width('100%')
    .height('100%')
    .backgroundColor('#f4f4f4')
    .onTouch((event) => this.listTouchEvent(event))// 父容器设置touch事件,当列表无数据也可以下拉刷新
    .onAppear(() => {
      this.refreshData()
    })
  }

  // 触摸事件
  listTouchEvent(event: TouchEvent){
    switch (event.type) {
      case TouchType.Down: // 手指按下
      // 记录按下的y坐标
        this.downY = event.touches[0].y
        this.lastMoveY = event.touches[0].y
        break
      case TouchType.Move: // 手指移动
      // 下拉刷新中 或 加载更多中,不进入处理逻辑
        if(this.isRefreshing || this.isLoading){
          console.info('========Move刷新中,返回=========')
          return
        }
      // 判断手势
        let isDownPull = event.touches[0].y - this.lastMoveY > 0
      // 下拉手势 或 已经进入了下拉刷新操作
        if ((isDownPull || this.isPullRefreshOperation) && !this.isCanLoadMore) {
          this.touchMovePullRefresh(event)
        } else {
          this.touchMoveLoadMore(event)
        }
        this.lastMoveY = event.touches[0].y
        break
      case TouchType.Up: // 手指抬起
      case TouchType.Cancel: // 触摸意外中断:来电界面
      // 刷新中 或 加载更多中,不进入处理逻辑
        if(this.isRefreshing || this.isLoading){
          console.info('========Up刷新中,返回=========')
          return
        }
        if (this.isPullRefreshOperation) {
          this.touchUpPullRefresh()
        } else {
          this.touchUpLoadMore()
        }
        break
    }
  }

  //============================================下拉刷新==================================================
  // 手指移动,处理下拉刷新
  touchMovePullRefresh(event:TouchEvent){
    // 当首部索引位于0
    if (this.startIndex == 0) {
      this.isPullRefreshOperation = true
      // 下拉刷新布局高度
      var height = vp2px(this.pullRefreshHeight)
      // 滑动的偏移量
      this.offsetY = event.touches[0].y - this.downY
      // 偏移量大于下拉刷新布局高度,达到刷新条件
      if (this.offsetY >= height) {
        // 状态1:松开刷新
        this.pullRefreshState(1)
        // 偏移量的值缓慢增加
        this.offsetY = height + this.offsetY * 0.15
      } else {
        // 状态0:下拉刷新
        this.pullRefreshState(0)
      }
      if (this.offsetY < 0) {
        this.offsetY = 0
        this.isPullRefreshOperation = false
      }
    }
  }

  // 手指抬起,处理下拉刷新
  touchUpPullRefresh(){
    // 是否可以刷新
    if (this.isCanRefresh) {
      console.info('======执行下拉刷新========')
      // 偏移量为下拉刷新布局高度
      this.offsetY = vp2px(this.pullRefreshHeight)
      // 状态2:正在刷新
      this.pullRefreshState(2)
      // 模拟耗时操作
      setTimeout(() => {
        this.refreshData()
        this.closeRefresh()
      }, 2000)
    } else {
      console.info('======关闭下拉刷新!未达到条件========')
      // 关闭刷新
      this.closeRefresh()
    }
  }

  // 下拉刷新状态
  // 0下拉刷新、1松开刷新、2正在刷新、3刷新成功
  pullRefreshState(state:number){
    switch (state) {
      case 0:
      // 初始状态
        this.pullRefreshText = '下拉刷新'
        this.pullRefreshImage = $r("app.media.pullrefresh")
        this.isCanRefresh = false
        this.isRefreshing = false
        break;
      case 1:
        this.pullRefreshText = '松开刷新'
        this.pullRefreshImage = $r("app.media.reset")
        this.isCanRefresh = true
        this.isRefreshing = false
        break;
      case 2:
        this.offsetY = vp2px(this.pullRefreshHeight)
        this.pullRefreshText = '正在刷新'
        this.pullRefreshImage = $r("app.media.refreshing")
        this.isCanRefresh = true
        this.isRefreshing = true
        break;
      case 3:
        this.pullRefreshText = '刷新成功'
        this.pullRefreshImage = $r("app.media.ic_refresh_succeed")
        this.isCanRefresh = true
        this.isRefreshing = true
        break;
    }
  }

  // 关闭刷新
  closeRefresh() {
    // 如果允许刷新,延迟进入,为了显示刷新中
    setTimeout(() => {
      var delay = 50
      if (this.isCanRefresh) {
        // 状态3:刷新成功
        this.pullRefreshState(3)
        // 为了显示刷新成功,延迟执行收缩动画
        delay = 500
      }
      animateTo({
        duration: 150, // 动画时长
        delay: delay, // 延迟时长
        onFinish: () => {
          // 状态0:下拉刷新
          this.pullRefreshState(0)
          this.isPullRefreshOperation = false
        }
      }, () => {
        this.offsetY = 0
      })
    }, this.isCanRefresh ? 500 : 0)
  }
  //============================================加载更多==================================================
  // 手指移动,处理加载更多
  touchMoveLoadMore(event:TouchEvent) {
    // 因为加载更多是在列表后面新增一个item,当一屏能够展示全部列表,endIndex 为 length+1
    if (this.endIndex == this.list.length - 1 || this.endIndex == this.list.length) {
      // 滑动的偏移量
      this.offsetY = event.touches[0].y - this.downY
      if (Math.abs(this.offsetY) > vp2px(this.loadMoreHeight)/2) {
        // 可以刷新了
        this.isCanLoadMore = true
        // 显示加载更多布局
        this.isVisibleLoadMore = true
        // 偏移量缓慢增加
        this.offsetY = - vp2px(this.loadMoreHeight) + this.offsetY * 0.1
      }
    }
  }
  // 手指抬起,处理加载更多
  touchUpLoadMore() {
    animateTo({
      duration: 200, // 动画时长
    }, () => {
      // 偏移量设置为0
      this.offsetY = 0
    })
    if (this.isCanLoadMore) {
      console.info('======执行加载更多========')
      // 加载中...
      this.isLoading = true
      // 模拟耗时操作
      setTimeout(() => {
        this.closeLoadMore()
        this.loadMoreData()
      }, 2000)
    } else {
      console.info('======关闭加载更多!未达到条件========')
      this.closeLoadMore()
    }
  }

  // 关闭加载更多
  closeLoadMore() {
    this.isCanLoadMore = false
    this.isLoading = false
    this.isVisibleLoadMore = false
  }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1327727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】五、数组与广义表

目录 一、定义 二、计算数组元素地址 三、稀疏矩阵快速转置 稀疏矩阵的表示 稀疏矩阵快速转置 四、广义表 一、定义 我们所熟知的一维、二维数组的元素是原子类型。广义表中的元素除了原子类型还可以是另一个线性表。当然所有的数据元素仍然属于同一类型。 这里的数组可…

Docker容器的日常维护和故障排除

Docker容器已经成为了现代应用程序开发和部署的核心工具之一。然而&#xff0c;为了确保容器环境的稳定性和可靠性&#xff0c;日常维护和故障排除是必不可少的任务。本文将介绍一些关键的Docker容器维护和故障排除技巧&#xff0c;并提供丰富的示例代码&#xff0c;以帮助大家…

Flink 状态管理与容错机制(CheckPoint SavePoint)的关系

一、什么是状态 无状态计算的例子&#xff1a; 例如一个加法算子&#xff0c;第一次输入235那么以后我多次数据23的时候得到的结果都是5。得出的结论就是&#xff0c;相同的输入都会得到相同的结果&#xff0c;与次数无关。 有状态计算的例子&#xff1a; 访问量的统计&#x…

python超实用插件REST Client、autoDocstring、Better Comments

1. autoDocstring 1.1 features 快速生成可以通过制表符浏览的文档字符串片段。在几种不同类型的文档字符串格式之间进行选择。通过pep484类型提示、默认值和变量名称推断参数类型。支持args、kwargs、装饰器、错误和参数类型。 1.2 用法 光标必须位于定义正下方的行上&am…

【数据结构】四、串

目录 一、定义 二、表示与实现 定长顺序存储 堆分配存储 链式存储 三、BF算法 四、KMP算法 1.求next数组 方法一 方法二&#xff08;考试方法&#xff09; 2.KMP算法实现 方法一 方法二 3.nextval 4.时间复杂度 本节最重要的就是KMP算法&#xff0c;其他要求不高…

pip 常用指令 pip config 命令用法介绍

&#x1f4d1;pip 常用命令归类整理 pip config 是一个用于管理本地和全局配置的命令行工具。它允许用户获取和设置所有的 pip 配置值。 命令 pip config 有以下参数 list&#xff1a;列出所有的 pip 配置值。edit&#xff1a;编辑 pip 配置文件。get&#xff1a;获取一个配…

时间是如何定义的

每年365天&#xff0c;每天24小时&#xff0c;每小时60分钟&#xff0c;每分钟60s&#xff0c;这是我们习以为常的时间计量单位&#xff0c;那么在继续往下&#xff0c;1s是多少&#xff1f;几时几刻、几点几分是如何确定的&#xff1f;带着这些问题&#xff0c;展开本文。 1、…

如何在 openKylin 上使用 ONLYOFFICE 桌面编辑器

文章作者&#xff1a;ajun ONLYOFFICE 桌面编辑器是一款基于依据 AGPL v.3 许可进行分发的开源办公套件。使用这款应用&#xff0c;您无需保持网络连接状态即可处理存储在计算机上的文档。 本文章基于中国根操作系统 openKylin 操作系统&#xff0c;使用软件商店快速安装与手…

rtsp视频在使用unity三维融合播放后的修正

1 rtsp 接入 我们使用unity UE 等三维渲染引擎中使用c编写插件来接入rtsp 视频。同时做融合的时候&#xff0c;和背景的三维颜色要一致&#xff0c;这就要使用视频融合修正技术。包括亮度&#xff0c;对比度&#xff0c;饱和度的修正。在单纯颜色上的修正可以简单使用rgb->…

Android 权限申请

在Android中&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用在运行时需要动态申请权限。以下是一些步骤来动态申请权限&#xff1a; 在应用的清单文件&#xff08;AndroidManifest.xml&#xff09;中声明需要的权限。例如&#xff0c;如果应…

前端FLV视频直播解决方案

项目背景&#xff1a; 1. 后台给出一个地址&#xff0c;持续不断的推送flv视频流。 2.前端需要接收视频流&#xff0c;并寻找合适的播放插件。 一开始&#xff1a; 其实用的是xgplayer&#xff08;西瓜视频&#xff09;。 官网地址&#xff1a;西瓜播放器 使用的是直播&a…

ardupilot开发 --- 风机不停机巡检 篇

在哪里创建的siyi实例&#xff1f; 如何传递飞控的时间戳给siyi相机&#xff1f; AP_RTC_ENABLED在waf编译时配置为1&#xff1f;&#xff1f; 如何配置&#xff1f; 在lua脚本中如何获取这个时间AP::rtc().get_utc_usec(utc_usec)&#xff1f;&#xff1f;&#xff1f; inclu…

【软件问题】解决 SecoClient 提示:接收返回码超时!

解决 SecoClient 提示&#xff1a;接收返回码超时&#xff01; 1.问题描述2.问题查找3.问题解决 系统&#xff1a;Win10 1.问题描述 这段时间因为不小心得了流感&#xff0c;所以需要请病假&#xff0c;而有些工作还得做不能落下&#xff0c;所以得居家办公&#xff0c;因为我…

【深入解析spring cloud gateway】12 gateway参数调优与分析

本节主要对网关主要的一些参数做一些解释说明&#xff0c;并用压测工具测试一下网关的接口&#xff0c;通过压测来验证参数配置是否合理 一、连接池参数 参数示例 spring:application:name: gatewaycloud:gateway:# http连接设置httpclient:# 全局的响应超时时间&#xff0c…

大语言模型(LLM)与 Jupyter 连接起来了!

现在&#xff0c;大语言模型&#xff08;LLM&#xff09;与 Jupyter 连接起来了&#xff01; 这主要归功于一个名叫 Jupyter AI 的项目&#xff0c;它是官方支持的 Project Jupyter 子项目。目前该项目已经完全开源&#xff0c;其连接的模型主要来自 AI21、Anthropic、AWS、Co…

【Git】在 IDEA 中合并多个 commit 为一个

文章目录 1 未提交到远程分支1.1 需求说明1.2 reset 操作1.3 再次 push 2 已经提交到远程分支2.1 需求说明2.2 rebase 操作2.3 强制 push 分两种情况&#xff1a; 一种是本地提交还没推到远程&#xff0c;这种好处理另一种是已经提交到远程分支&#xff0c;这个略麻烦 1 未提…

【Java代码审计】RCE篇

【Java代码审计】RCE篇 1.Java中的RCE2.ProcessBuilder命令执行漏洞3.Runtime exec命令执行漏洞4.脚本引擎代码注入5.RCE的防御 1.Java中的RCE 在PHP开发语言中有system()、exec()、shell_exec()、eval()、passthru()等函数可以执行系统命令。在Java开发语言中可以执行系统命令…

如何从 Android 手机免费恢复已删除的通话记录/历史记录?

有一个有合作意向的人给我打电话&#xff0c;但我没有接听。更糟糕的是&#xff0c;我错误地将其删除&#xff0c;认为这是一个骚扰电话。那么有没有办法从 Android 手机恢复已删除的通话记录呢&#xff1f;” 塞缪尔问道。如何在 Android 上恢复已删除的通话记录&#xff1f;如…

STM32CubeMX驱动ST7789

环境 1、单片机:STM32F103C8T6 2、开发平台&#xff1a;STM32CUBEMXkeil mdk 3、屏幕&#xff1a;ST7789&#xff0c;分辨率240*240 STM32配置 1、使用硬件SPI1驱动屏幕。配置如下&#xff1a; 2、屏幕控制引脚配置&#xff1a; 注意&#xff1a;只配置了DC,RST,CS这3个控…

BearPi Std 板从入门到放弃 - 后天篇(3)(ESP8266透传点灯)

简介 电脑搭建一个TCP Server&#xff0c; ESP8266 串口设置好透传模式, 再由TCP Server发送指令控制灯的亮灭; 开灯指令&#xff1a; led_on回车 &#xff1b; 关灯指令: led_off回车 主芯片: STM32L431RCT6 LED : PC13 \ 推挽输出即可 \ 高电平点亮 串口: Usart1 / LPUART E…