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

server/2024/9/24 9:51:56/

鸿蒙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.ppmy.cn/server/121290.html

相关文章

抓机遇,促发展——2025第十二届广州国际汽车零部件加工技术及汽车模具展览会

新能源时代&#xff0c;电动化、智能化正在重塑全球汽车市场格局。中国自主品牌新能源汽车的市占率不断提升、头部效应初显&#xff0c;更有机会带动相关供应链企业成长。中国的零部件企业有望抓住变局下的机会&#xff0c;在新一轮竞争中崛起。 智能电动车时代&#xff0c;汽车…

Windows11系统安装,配置CUDA、cuDNN等

已经有大几年没有安装过 Windows 的系统了&#xff0c;今天因为黑神话悟空&#xff0c;准备把 Win 11 装一台&#xff0c;玩玩游戏&#xff0c;顺便把一些 CUDA 相关的异步解析项目也安装到 Window 上。 下载安装 PE 因为十几年前&#xff0c;只会用 PE 装系统&#xff0c;所…

mysql学习教程,从入门到精通,SQL 删除表(DROP TABLE 语句)(20)

1、SQL 删除表&#xff08;DROP TABLE 语句&#xff09; 在SQL中&#xff0c;DROP TABLE语句用于删除数据库中的一个或多个表&#xff0c;同时删除表中的所有数据、索引、触发器、约束和表结构本身。这是一个非常强大的命令&#xff0c;因此在使用时需要格外小心&#xff0c;因…

基于单片机控制的程控开关电源研究

摘 要 : 在开关电源控制方案中 , 建立于单片机控制基础方式上的程控开关电源方案是一种比较有效的方式 。 利用单片机实现对程控开关的控制, 可以减少设计复杂度 、 增加控制可靠性 , 值得投入更多的精力进行研究和推进 。 本文就这一控制方法进行了详细的探讨 。 关键词…

基于web的工作管理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

AI辅助编码工具如何影响着程序员开发群体

AI辅助编码工具的出现对程序员开发群体产生了深远的影响&#xff0c;有一些初步基础的程序员&#xff0c;可以借助AI工具的加持&#xff0c;生产效率大大提升&#xff0c;达到中高级程序员的水平。 这些影响可以从多个角度来分析&#xff1a; 提高开发效率&#xff1a; AI工具…

基于drools和flowable实现的智能决策引擎

在现代企业中&#xff0c;业务流程的自动化和智能化是提高运营效率的关键。智能决策体系通过结合工作流引擎、规则引擎和大语言模型&#xff08;LLM&#xff09;&#xff0c;为企业提供了一种强大的决策支持工具。 智能决策引擎主要由三部分组成 工作流引擎&#xff1a;自动化…

【Python报错已解决】AttributeError: ‘WindowsPath‘ object has no attribute ‘rstrip‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…