HarmonyOS鸿蒙开发实战(5.0)悬浮窗拖拽和吸附动画实践

鸿蒙HarmonyOS NEXT开发实战往期文章必看(持续更新......)

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

HarmonyOS NEXT应用开发案例实践总结合集

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

非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!


介绍

本示例使用position绝对定位实现应用内悬浮窗,并且通过animateTo结合curves动画曲线实现悬浮窗拖拽跟手和松手吸附边缘的弹性动画效果。

效果图预览

使用说明

按住悬浮窗可以拖拽,松开后悬浮窗自动靠左或靠右,如果悬浮窗超出内容区上下边界,自动吸附在边界位置。

实现思路

  1. 悬浮窗组件使用Stack嵌套video布局,使用属性position绝对定位使组件悬浮。源码参考FloatWindowMainPage.ets
Stack({ alignContent: Alignment.Bottom }) {Video({src: $rawfile('float_window_video.mp4'),controller: this.videoController}).controls(false).autoPlay(true).loop(true).muted(true).width($r('app.string.float_window_full_size')).onClick(() => {this.videoController.requestFullscreen(true);}).borderRadius($r('app.integer.float_window_content_border_radius'))Text($r('app.string.float_window_live_text')).width($r('app.string.float_window_full_size')).fontSize($r('app.string.ohos_id_text_size_body1')).fontColor($r('app.color.ohos_id_color_background')).textAlign(TextAlign.Center).backgroundColor($r('app.color.ohos_id_color_list_alert')).borderRadius({bottomLeft: $r('app.integer.float_window_content_border_radius'),bottomRight: $r('app.integer.float_window_content_border_radius')})
}
.clip(true)
.border({width: $r('app.integer.float_window_border_width'),color: $r('app.color.ohos_id_color_background')
})
.borderRadius($r('app.string.ohos_id_corner_radius_default_l'))
.width(Constants.FLOAT_WINDOW_WIDTH)
.height(Constants.FLOAT_WINDOW_HEIGHT)
.backgroundColor($r('app.color.ohos_id_color_foreground'))
.position(this.edge)
.onTouch((event: TouchEvent) => {this.onTouchEvent(event);
})
  1. 初始化时悬浮窗的position属性设置top和right,让悬浮窗靠右。源码参考FloatWindowMainPage.ets
  @State edge: Edges = { top: Constants.INIT_POSITION_Y, right: Constants.PAGE_PADDING };
  1. 父组件添加onAreaChange回调,获取父组件的宽高。源码参考FloatWindowMainPage.ets
  // 父组件宽度@State containerWidth: number = 0;// 父组件高度@State containerHeight: number = 0;.onAreaChange((oldValue: Area, newValue: Area) => {// TODO:性能知识点:onAreaChange是高频回调,仅在父组件尺寸改变时获取新的父组件宽高,避免性能损耗if (oldValue.width !== newValue.width) {this.containerWidth = newValue.width as number;}if (oldValue.height !== newValue.height) {this.containerHeight = newValue.height as number;}})
  1. 悬浮窗组件添加onTouchEvent回调,在手指按下时保存触摸点在窗口中的坐标,用于移动时悬浮窗位置的计算。源码参考FloatWindowMainPage.ets
  // 拖拽移动开始时悬浮窗在窗口中的坐标,每次移动回调触发时更新private windowStartX: number = 0;private windowStartY: number = 0;case TouchType.Down: {// 获取拖拽开始时悬浮窗在窗口中的坐标this.windowStartX = event.touches[0].windowX;this.windowStartY = event.touches[0].windowY;break;}
  1. 手指移动时,获取触摸点相对于应用窗口左上角的X和Y坐标,通过计算设置悬浮窗的position坐标实现拖拽,使用默认参数的弹性跟手动画曲线curves.responsiveSpringMotion结合animateTo实现跟手动画效果。源码参考FloatWindowMainPage.ets
  case TouchType.Move: {const windowX: number = event.touches[0].windowX;const windowY: number = event.touches[0].windowY;// TODO:知识点:跟手动画,推荐使用默认参数的弹性跟手动画曲线curves.responsiveSpringMotion。animateTo({ curve: curves.responsiveSpringMotion() }, () => {// 判断当前edge中属性left和right哪个不为undefined,用于控制悬浮窗水平方向的位置if (this.edge.left !== undefined) {this.edge.left = this.edge.left as number + (windowX - this.windowStartX);} else {this.edge.right = this.edge.right as number - (windowX - this.windowStartX);}this.edge.top = this.edge.top as number + (windowY - this.windowStartY);this.windowStartX = windowX;this.windowStartY = windowY;})break;}
  1. 手指抬起时,通过判断悬浮窗中心在水平方向位于窗口中心的左侧或右侧设置悬浮窗靠左或靠右,如果悬浮窗超出内容区上下边界,则将悬浮窗设置在边界位置,使用curves.springMotion弹性动画曲线实现吸附边界时的弹性动画效果。源码参考FloatWindowMainPage.ets
  case TouchType.Up: {// 计算悬浮窗中心点在父组件中水平方向的坐标let centerX: number;if (this.edge.left !== undefined) {centerX = this.edge.left as number + Constants.FLOAT_WINDOW_WIDTH / 2;}else{centerX = this.containerWidth - (this.edge.right as number) - Constants.FLOAT_WINDOW_WIDTH / 2;}// TODO:知识点:通过判断悬浮窗在父组件中的位置,设置悬浮窗贴边,使用curves.springMotion()弹性动画曲线,可以实现阻尼动画效果animateTo({ curve: curves.springMotion() }, () => {// 判断悬浮窗中心在水平方向是否超过父组件宽度的一半,根据结果设置靠左或靠右if (centerX > (this.containerWidth / 2)) {this.edge.right = Constants.PAGE_PADDING;this.edge.left = undefined;} else {this.edge.right = undefined;this.edge.left = Constants.PAGE_PADDING;}// 判断悬浮窗是否超出内容区上下边界,根据结果将悬浮窗设置在边界位置if (this.edge.top as number < Constants.PAGE_PADDING) {this.edge.top = Constants.PAGE_PADDING;} else if (this.edge.top as number > this.containerHeight - Constants.FLOAT_WINDOW_HEIGHT - Constants.PAGE_PADDING) {this.edge.top = this.containerHeight - Constants.FLOAT_WINDOW_HEIGHT - Constants.PAGE_PADDING;}})break;}

高性能知识点

不涉及

工程结构&模块类型

floatwindow                                  // har类型
|---/src/main/ets/common                        
|   |---Constants.ets                        // 常量
|---/src/main/ets/pages                        
|   |---FloatWindowMainPage.ets              // 视图层-悬浮窗首页

模块依赖

  1. 本示例依赖动态路由模块来实现页面的动态加载。

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为体系杂乱无章,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)路线、视频、文档用来跟着学习是非常有必要的。

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

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

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


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

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

路线图适合人群:

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

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

(鸿蒙语法ArkTS、TypeScript、ArkUI教程……)全球开发者的开源社区,开源代码

 纯血版鸿蒙全套学习文档(面试、文档、全套视频等)全球开发者的开源社区,开源代码

                   

鸿蒙APP开发必备

​​

总结

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

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

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

相关文章

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【Perf调测】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 基本概念 Perf为性能分析工具&#xff0c;依赖PMU&#xff08;Per…

代码随想录打卡Day41

最近事情好多。。全堆一块了&#xff0c;今天先写两题吧&#xff0c;剩下一题明天解决。 121. 买卖股票的最佳时机 这道题纯不会&#xff0c;不知道该怎么构造dp数组&#xff0c;更不知道dp数组的含义&#xff0c;看完讲解以后感觉这样的dp数组构造还挺巧妙的&#xff0c;第一…

Qt --- 常用控件的介绍 --- 其他控件

一、QPushButton QWidget中设计到的各种属性/函数/使用方法&#xff0c;针对接下来要介绍的Qt的各种控件都是有效的。 使用QPushButton表示一个按钮&#xff0c;这也是当前我们最熟悉的一个控件了。这个类继承了QAbstractButton&#xff0c;这个类是一个抽象类&#xff0c;是…

C++自动驾驶面试核心问题整理

应用开发 概述&#xff1a;比较基础&#xff0c;没啥壁垒&#xff0c;主要有linux开发经验即可 问题&#xff1a;基础八股&#xff0c;如计算机网络、操作系统、c11等基础三件套&#xff1b;中等难度算法题1-2道。 中间件开发&#xff08;性能优化&#xff09; 概述&am…

Set 和 Map 的模拟实现

1、引言 在数据结构与算法的学习与实践中&#xff0c;关联容器&#xff08;associative containers&#xff09;是不可忽视的重要工具。作为高效管理数据的一类容器&#xff0c;C 标准库中的 set 和 map 在现代软件开发中扮演着关键角色。这两个容器通过平衡二叉搜索树&#x…

【通讯协议】S32K142芯片——LIN通信的学习和配置

文章目录 前言1.LIN是什么&#xff1f;2. LIN连接结构及节点构成3. 帧的组成3.1 帧头3.1.1 同步间隔场&#xff08;Break&#xff09;3.1.2 同步场&#xff08;Synch&#xff09;3.1.3 标识符场&#xff08;PID&#xff09; 3.2 帧响应3.2.1 数据场3.2.2 校验和场 3. 代码配置总…

leetcode热题100.最长回文子串(动态规划解法)

题目 5. 最长回文子串 - 力扣&#xff08;LeetCode&#xff09; 给你一个字符串 s&#xff0c;找到 s 中最长的 回文子串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba" 同样是符合题意的答…

【图灵完备 Turing Complete】游戏经验攻略分享 Part.6 处理器架构2 函数

新的架构来了&#xff0c;本游戏的最后一个攻略分享&#xff0c;最后汇编部分无非是对于操作码的熟练&#xff0c;硬件没有问题&#xff0c;那么也就无关痛痒了。 汇编实现&#xff0c;两数相或和两数相与非一起相与即可。 八位异或器&#xff0c;整就完事了。 有手就行。 利…

設置Android設備全局代理

全局代理是指在設備上設置一個代理伺服器&#xff0c;使所有的網路請求都通過這個代理伺服器進行轉發。這樣&#xff0c;無論你使用的是哪款應用&#xff0c;所有的網路流量都會經過代理伺服器&#xff0c;從而實現統一的網路訪問控制和隱私保護。 配置Wi-Fi網路代理 在Andro…

干货满满:嵌入式电阻的重要作用全知晓

在嵌入式开发中&#xff0c;有一个小小的元件&#xff0c;它看似不起眼&#xff0c;却在电路中扮演着极其重要的角色。它就是——电阻。很多初学者认为电阻只是用来“分压降流”&#xff0c;但其实&#xff0c;电阻的作用远比我们想象的要复杂和关键。今天&#xff0c;我们就来…

Pyecharts在数据可视化大屏中的应用与实践

Pyecharts在数据可视化大屏中的应用与实践 在大数据时代&#xff0c;数据可视化已成为企业决策、业务分析不可或缺的一环。而数据大屏&#xff0c;作为数据可视化的高端表现形式&#xff0c;不仅能够实时展示关键业务指标&#xff0c;还能通过丰富的图表和动态效果&#xff0c…

LeetCode 2374.边积分最高的节点:模拟

【LetMeFly】2374.边积分最高的节点&#xff1a;模拟 力扣题目链接&#xff1a;https://leetcode.cn/problems/node-with-highest-edge-score/ 给你一个有向图&#xff0c;图中有 n 个节点&#xff0c;节点编号从 0 到 n - 1 &#xff0c;其中每个节点都 恰有一条 出边。 图…

TM-align蛋白质聚类数据格式转化

TM-align 对蛋白质结构中的序列进行同源性聚类分析的结果格式如下&#xff1a; 8p0k_H 8p0k_H 8p0k_H 8p0n_H 8p0k_H 8p0j_H 8p0v_M 8p0v_M 8p0y_O 8p0y_O 8p0y_O 8p10_O 8p0y_O 8p0y_A 8p0y_O 8p10_D 8p0y_O 8p24_V 8p0y_O 8p24_Z 其中&#xff0c;第一列为聚类的代表序列&a…

思科安全网络解决方案

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

【门牌制作 / A】

题目 代码 #include <bits/stdc.h> using namespace std; int main() {int cnt 0;for (int i 1; i < 2020; i){string s;s to_string(i);cnt count(s.begin(), s.end(), 2);}cout << cnt; }

【C++篇】走进C++标准模板库:STL的奥秘与编程效率提升之道

文章目录 C STL 初探&#xff1a;打开标准模板库的大门前言第一章: 什么是STL&#xff1f;1.1 标准模板库简介1.2 STL的历史背景1.3 STL的组成 第二章: STL的版本与演进2.1 不同的STL版本2.2 STL的影响与重要性 第三章: 为什么学习 STL&#xff1f;3.1 从手动编写到标准化解决方…

【论文速看】DL最新进展20240923-长尾综述、人脸防伪、图像分割

目录 【长尾学习】【人脸防伪】【图像分割】 【长尾学习】 [2024综述] A Systematic Review on Long-Tailed Learning 论文链接&#xff1a;https://arxiv.org/pdf/2408.00483 长尾数据是一种特殊类型的多类不平衡数据&#xff0c;其中包含大量少数/尾部类别&#xff0c;这些类…

tomcat服务搭建部署ujcms网站

tomcat服务搭建部署ujcms网站 关闭selinux和防火墙 setenforce 0 && systemctl stop firewalld安装java环境 #卸载原有java8环境 yum remove java*#上传java软件包&#xff0c;并解压缩 tar -xf openjdk-11.0.1_linux-x64_bin.tar.gz && mv jdk-11.0.1 jdk11…

docker 镜像,导入导出,

dockers镜像传输&#xff1a;docker save和docker load命令的使用_docker save -o-CSDN博客 docker save 命令 docker load 命令 快速复制容器-CSDN博客 创建docker容器报错:Error response from daemon: No command specified-CSDN博客 Docker 镜像移动或复制到另一台服务器_d…

了解函数式编程:从表象到本质,从技法到心法

今天看到&#xff0c;《代码整洁之道》&#xff08;Clean Code&#xff09;和《架构整洁之道》&#xff08;Clean Architecture&#xff09;的作者Robert C. Martin在讨论函数式编程时曾提到&#xff1a; 函数式编程不仅仅是“用函数编程”。函数式编程是没有赋值语句的编程。 …