拓冰建站拓冰建站
首页 / 资讯中心 / 正文

HarmonyOS Next 系列之可移动悬浮按钮实现(六)

系列文章目录HarmonyOS Next 系列之省市区弹窗选择器实现一HarmonyOS Next 系列之验证码输入组件实现二HarmonyOS Next 系列之底部标签栏TabBar实现三HarmonyOS Next 系列之HTTP请求封装和Token持久化存储四HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现五HarmonyOS Next 系列之可移动悬浮按钮实现六HarmonyOS Next 系列之沉浸式状态实现的多种方式七HarmonyOS Next系列之Echarts图表组件折线图、柱状图、饼图等)实现八HarmonyOS Next系列之地图组件Map Kit使用九HarmonyOS Next系列之半圆环进度条实现十HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现十一HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图十二系列文章目录2【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器上【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器下【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇上【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇下【鸿蒙】HarmonyOS Next 组件或页面之间的所有通信传参方法总结文章目录系列文章目录系列文章目录2前言一、实现原理分析二、API简单回顾三、规避和限制移动范围四、窗口宽高、状态栏高度、底部规避区域高度获取1、窗口宽高获取2、状态栏高度获取2、底部规避区域高度获取四、完整代码实现五、其他说明前言HarmonyOS Next基于API11实现一个可移动的悬浮按钮ps为演示作用这边和后续代码例子随便用回到顶部图标来做演示实际可自定义替换一、实现原理分析1、布局方面使用Stack容器让悬浮按钮堆叠在页面之上通过postion属性x,y设置悬浮按钮位置x,y为相对页面左上角距离2、事件处理在移动过程中通过监听touch事件获取手指在屏幕上位置与初始触摸点位置比较计算悬浮按钮的偏移量动态更新悬浮按钮x,y值。二、API简单回顾touch触摸事件1、触摸类型TouchType名称描述Down手指按下时触发。Up手指抬起时触发。Move手指按压态在屏幕上移动时触发。2、手指信息TouchObject名称描述type触摸事件的类型windowX触摸点相对于应用窗口左上角的X坐标。windowY触摸点相对于应用窗口左上角的Y坐标。说明以x轴为例计算两个触摸点(A、B)水平方向距离只需B.windowX-A.windowX而在我们实现悬浮按钮处理过程中这个A点就是手指刚按下去触摸点的windowXB点就是移动过程中触摸点的windowX在移动过程中不断计算这个差值后更新悬浮按钮坐标就能让其跟着手指移动。当然在这个过程中还需要考虑悬浮按钮移出屏幕情况需要规避和限制。pswindowX、windowY单位为vp三、规避和限制移动范围为了让悬浮按钮不移出屏幕需要限制x、y大小最小值很容易想到x0,y0也即悬浮按钮在最左上角最大值位置在页面右下角假设悬浮按钮半径为R窗口宽为winWidth、窗口高winHeight状态栏高statusHeight,底部规避区域高bottomHeightx最大值winWidth-2Ry最大值winHeight-2R-statusHeight-bottomHeight所以x范围为0~winWidth-2Ry范围0 ~winHeight-2R-statusHeight-bottomHeight四、窗口宽高、状态栏高度、底部规避区域高度获取1、窗口宽高获取import{window}fromkit.ArkUI...............window.getLastWindow(getContext(this),(err,windowClass){if(!err.code){//获取窗口宽高letwindowPropertieswindowClass.getWindowProperties()this.winWidthpx2vp(windowProperties.windowRect.width)this.winHeightpx2vp(windowProperties.windowRect.height)}})2、状态栏高度获取import{window}fromkit.ArkUI...............window.getLastWindow(getContext(this),(err,windowClass){if(!err.code){//获取状态栏高度this.statusHeightpx2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height)}})2、底部规避区域高度获取import{window}fromkit.ArkUI...............window.getLastWindow(getContext(this),(err,windowClass){if(!err.code){//获取手机底部规避区域高度this.bottomAvoidAreaHeightpx2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height)}})ps:需要注意的是上述获取到的宽高单位都是px需要统一转成vp单位方便和windowXY进行计算四、完整代码实现SuspensionButton .etsimport{window}fromkit.ArkUIEntry Component struct SuspensionButton{State statusHeight:number0//状态栏高度State bottomAvoidAreaHeight:number0//手机底部规避区域高度State curLeft:number0//当前悬浮按钮距离窗口左边距离State curTop:number0//当前悬浮按钮距离窗口顶部距离privatestartLeft:number0//开始移动那一刻悬浮按钮距离窗口左边距离privatestartTop:number0//开始移动那一刻悬浮按钮距离窗口顶部距离privatestartX:number0//开始移动触摸点x坐标相对窗口左上角privatestartY:number0//开始移动触摸点y坐标相对窗口左上角privateradius:number25//悬浮按钮半径单位vpprivatewinWidth:number0//窗口宽度privatewinHeight:number0//窗口高度aboutToAppear(){this.getWindowInfo()}//获取窗口尺寸信息getWindowInfo(){window.getLastWindow(getContext(this),(err,windowClass){if(!err.code){//状态栏高度this.statusHeightpx2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height)//获取手机底部规避区域高度this.bottomAvoidAreaHeightpx2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height)//获取窗口宽高letwindowPropertieswindowClass.getWindowProperties()this.winWidthpx2vp(windowProperties.windowRect.width)this.winHeightpx2vp(windowProperties.windowRect.height)//设置初始位置位于屏幕右下角演示设置可根据实际调整this.curLeftthis.winWidth*0.8this.curTopthis.winHeight*0.8}})}build(){Stack(){Column(){//页面内容}.width(100%).height(100%)//悬浮按钮Row(){Image($r(app.media.top)).width(25)}.width(this.radius*2).height(this.radius*2).justifyContent(FlexAlign.Center).borderRadius(this.radius).backgroundColor(#E8E8E8).position({x:this.curLeft,y:this.curTop}).onTouch((event:TouchEvent){//手指按下记录初始触摸点坐标、悬浮按钮位置if(event.typeTouchType.Down){this.startXevent.touches[0].windowXthis.startYevent.touches[0].windowYthis.startLeftthis.curLeftthis.startTopthis.curTop}//手指拖动elseif(event.typeTouchType.Move){lettouchevent.touches[0]//计算悬浮球与左边距离x坐标 当前悬浮球距离左边开始位置(x轴)当前触摸点x坐标-开始移动触摸点x坐标letcurLeftthis.startLeft(touch.windowX-this.startX)//限制悬浮球不能移除屏幕左边curLeftMath.max(0,curLeft)//限制悬浮球不能移除屏幕右边this.curLeftMath.min(this.winWidth-2*this.radius,curLeft)//计算悬浮球与顶部距离y坐标 当前悬浮球距离顶部开始位置(y轴)当前触摸点y坐标-开始移动触摸点y坐标letcurTopthis.startTop(touch.windowY-this.startY)//限制悬浮球不能移除屏幕上边curTopMath.max(0,curTop)//限制悬浮球不能移除屏幕下边this.curTopMath.min(this.winHeight-2*this.radius-this.bottomAvoidAreaHeight-this.statusHeight,curTop)}})}.width(100%).height(100%).backgroundColor(#f2f2f2)}}运行效果请用真机调试预览器会显示异常五、其他说明如果是想实现悬浮窗原理也一样只不过把悬浮按钮半径计算拆开为x,y2个方向根据悬浮窗宽高替换带入计算即可。如果想实现不可移动悬浮按钮类似案例中回到顶部固定在页面右下角只需要把触摸事件去掉即可。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门