HarmonyOS开发实战(5.0)实现二楼上划进入首页效果详解

鸿蒙HarmonyOS开发实战往期必看文章:

HarmonyOS NEXT应用开发性能实践总结

一分钟了解"纯血版!鸿蒙HarmonyOS Next应用开发!

最新版!"非常详细的" 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通)


介绍

本示例主要介绍了利用position和onTouch来实现首页下拉进入二楼、二楼上划进入首页的效果场景,利用translate和opacity实现动效的移动和缩放,并将界面沉浸式(全屏)显示。

效果图预览

使用说明

  1. 向下滑动首页页面超过回弹触发高度位于中间部分时,页面触发刷新列表数据,刷新完成后回弹。
  2. 向下滑动首页页面超过刷新列表触发高度,页面进入二楼。
  3. 向下滑动未超过触发高度页面回弹。
  4. 二楼页面向上滑动超过触发高度,页面进入首页,未超过触发高度页面回弹。
  5. 效果图因要展示动效效果对展开速度进行了调整,可以通过SecondFloor.ets中expandSecondFloor的动效时长来调整二楼展开的速度,也可通过FloorView.ets中的OFFSET_STEP和EXPAND_FLOOR_INTERVAL_TIME来调整一楼展开的速度。

实现思路

本例涉及的关键特性和实现方案如下:

  1. 使用Column布局将一楼页面二楼页面包裹,使用position将一、二楼页面固定,floorHeight设置二楼高度(初始Y轴为负的二楼高度),使用clip按指定的形状对当前组件进行裁剪,源码参考SecondFloor.etsFloorView.ets

    复制代码
    Column() {
      // 二楼页面
      Column() {
        this.floorViewBuilder();
      }
      // 固定二楼刚开始位置
      .position({
        x: 0,
        // Y轴大小
        y: this.mainPageOffsetY
      })
      ...
      // 一楼页面
      Column() {
        this.mainPageBuilder();
      }
      .position({
        x: 0,
        // Y轴大小加上二楼高度
        y: this.offsetY + this.floorHeight
      })
    }
    .clip(true) // TODO:知识点:按指定的形状对当前组件进行裁剪,参数为boolean类型时,设置是否按照父容器边缘轮廓进行裁剪。
  2. 通过对Column设置onTouch属性,记录手指按下和离开屏幕Y轴坐标,判断手势是上/下滑,当下滑距离达到触发距离进入二楼,未达到触发距离则刷新数据或直接回弹(以一楼页面下滑为例),源码参考SecondFloor.ets

    复制代码
    Column() {
      ...
      // 一楼页面
      Column() {
        this.mainPageBuilder();
      }
      ...
    }
      .onTouch((event) => {
        switch (event.type) {
          case TouchType.Down:
            this.onTouchDown(event);
            break;
          case TouchType.Move:
            this.onTouchMove(event);
            break;
            ...
            break;
        }
        event.stopPropagation(); // 阻止冒泡
      })
            
    /**
     * 按下事件、获取按下事件的位置
     * @param event 触屏事件
     */
    private onTouchDown(event: TouchEvent) {
      // 获取触发按压事件Y轴的位置
      this.lastY = event.touches[0].windowY;
      ...
    }
    
    /**
     * 滑动事件
     * @param event 触屏事件
     */
    private onTouchMove(event: TouchEvent) {
      ...
      let currentY = event.touches[0].windowY;
      // onTouch事件中本次Y轴大小减去上一次获取的Y轴大小,为负值则是向上滑动,为正值则是向下滑动
      let deltaY = currentY - this.lastY;
      ...
    }
  3. 使用Row布局将刷新动画包裹,使用rotate实现图片圆圈的转动,源码参考SecondFloor.ets

    复制代码
    Row() {
      // this.floorHeight - Math.abs(this.offsetY)为下拉距离,下拉距离超过MINI_SHOW_DISTANCE(动效最小展示距离)且小于TRIGGER_HEIGHT(触发动画高度或者动效消失高度)展示动画
      if ((this.floorHeight - Math.abs(this.offsetY)) > MINI_SHOW_DISTANCE && (this.floorHeight - Math.abs(this.offsetY)) <= TRIGGER_HEIGHT) {
        Row() {
          Image($r("app.media.second_floor_user_loading"))
            // ...
            .rotate({ angle: this.rotateAngle })
        }
      }
    }
  4. 滑动到中间位置时触发刷新动画,刷新时固定高度,刷新完成后回弹到一楼,源码参考SecondFloor.ets

    复制代码
    /**
     * 刷新列表方法
     */
    private UpdateUserData(): void {
      animateTo({
      duration: ANIMATION_DURATION, // 动画时长
      curve: Curve.Ease, // 动画曲线
      iterations: -1, // 播放次数,-1为无限循环
      playMode: PlayMode.Normal, // 动画模式
      }, () => {
        this.rotateAngle = ROTATE_ANGLE;
      })
      // 模拟网络加载耗时2s,结束后回弹
      setTimeout(() => {
        // 归零图片角度
        this.rotateAngle = 0;
        // 由于本案例仅有6条模拟数据,此处根据数据列表索引值随机改变列表项,模拟列表刷新
        this.userInfoList.forEach((value: UserInformation, index: number) => {
          this.userInfoList[index] =
            new UserInformation($r(`app.media.second_floor_ic_public_user${Math.floor((Math.random() * 6) + 1)}`),
              `User${Math.floor((Math.random() * 6) + 1)}`,
              `lastMsg${Math.floor((Math.random() * 6) + 1)}`);
        })
        // 加载完成后回弹到一楼
        this.scrollByTop();
      }, UPDATE_TIME)
    }
    
    /**
     * 刷新时回弹到固定高度
     */
    private scrollByUpdate(): void {
      this.backAnimator = animator.create({
        duration: 350,
        easing: "linear",
        // 动画延时播放
        delay: 0,
        // 动画结束后保持结束状态
        fill: "forwards",
        direction: "normal",
        // 播放次数
        iterations: 1,
        begin: this.offsetY,
        // 设置加载时页面从拉取的位置回弹到固定高度
        end: -this.floorHeight + UPDATE_HEIGHT
      })
      this.backAnimator.onFrame = (value: number) => {
        this.offsetY = value;
      }
      this.backAnimator.play();
    }
  5. 在手指滑动结束离开屏幕后,通过判断此时二楼高度与Y轴高度差是否大于触发距离,若大于触发距离将进入二楼,若小于则触发刷新数据或直接回弹(以一楼下滑为例),源码参考SecondFloor.ets

    复制代码
    /**
     * 触摸抬起或取消触摸事件
     */
    private onTouchUp(): void {
      if (this.dragging) {
        // 二楼自身的高度减去向下Y轴的位移的绝对值大于触发值进入二楼,否则回弹
        if ((this.floorHeight - Math.abs(this.offsetY)) > this.expandFloorTriggerDistance) {
        // 进入二楼
        this.expandSecondFloor();
        } else if ((this.floorHeight - Math.abs(this.offsetY)) <= this.expandFloorTriggerDistance &&
          (this.floorHeight - Math.abs(this.offsetY)) > BACK_HEIGHT) {
          // 设定滑动结束在大于200小于100的中间位置触发刷新数据
          this.scrollByUpdate();
          this.UpdateUserData();
        } else {
          // 未达到触发距离回弹
          this.scrollByTop();
        }
      }
    }

高性能知识点

本例使用了onTouch事件实时监听获取相关数据,避免在函数中进行冗余或耗时操作,例如应该减少或避免在函数打印日志,会有较大的性能损耗。

本示例使用了setInterval进行页面移动控制,在页面移动到相应的位置后使用clearInterval销毁以降低内存占用。

工程结构&模块类型

复制代码
secondfloorloadanimation                     // har类型
|---model 
|   |---AppInfo.ets                          // App信息
|   |---UserInformation.ets                  // 用户信息    
|---view
|   |---FloorView.ets                        // 视图层-应用二楼页面
|   |---SecondFloor.ets                      // 视图层-应用一楼页面
|   |---SecondFloorLoadAnimation.ets         // 视图层-应用主页面

模块依赖

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)路线图、学习视频、文档用来跟着学习是非常有必要的。

如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员

鸿蒙 NEXT 全栈开发学习笔记希望这一份鸿蒙学习文档能够给大家带来帮助~

这份鸿蒙(HarmonyOS NEXT)包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、(南向驱动、嵌入式等)鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。


鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员: 想要拓展职业边界
零基础小白: 鸿蒙爱好者,希望从0到1学习,增加一项技能。
**技术提升/进阶跳槽:**发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频学习教程+学习PDF文档

HarmonyOS Next 最新全套视频教程

纯血版鸿蒙全套学习文档(面试、文档、全套视频等)

​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线

相关推荐
一只栖枝16 分钟前
华为 HCIE 大数据认证中 Linux 命令行的运用及价值
大数据·linux·运维·华为·华为认证·hcie·it
加班是不可能的,除非双倍日工资2 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi3 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip3 小时前
vite和webpack打包结构控制
前端·javascript
excel4 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国4 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼4 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy4 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
zhanshuo4 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
harmonyos
zhanshuo4 小时前
在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
harmonyos