【如此之白】OpenHarmony ArkUI实现Web API Drag拖拽效果 原创 精华
大家经常浏览网页,是不是发现鼠标按住图片拖动后,可以拖出一个虚影。
对于WEB前端,Web API提供drag接口,很简单就可以实现一个这样的效果。
对于OpenHarmony应用开发的小伙伴们,我们也可以利用onTouch实现一个这样的效果。
拖拽效果展示
完整代码查看:
https://gitee.com/hytyj_hamstermie/tian-open-document.git
ArkUI实现Web API Drag拖拽效果/demo/page.ets
实现思路
实现思路很简单。
我们设置一个模拟块
,这个模拟块
是永远叠在最上面的。
模拟块
一开始是隐藏的。
当用户触摸到绑定touch事件的一个固定块
后,这个模拟块将拷贝该固定块
的所有样式、内容,并获取该固定块
的位置。
显示模拟块
,并覆盖在固定块
上。
在触摸事件持续过程中,模拟块
跟随手指触摸坐标进行自身的位移更新。
在触摸事件结束后,模拟块
消失。
开发环境
- IDE: DevEco Studio 3.0beta2 Build Version 3.0.0.800
- SDK Version: 8
- supportSystem “standard”
- 系统版本:OpenHarmony 3.1beta
实践
效果如图:
定义块样式
首先,我们先定义出固定块的样式。使用@Extend装饰器,我们可以更快地复制块样式。
使用@Extend装饰器
IDE中使用@Extend装饰器会报错Duplicate function implementation.
但OpenHarmony是支持@Extend装饰器的。推测可能属于IDE问题,这里推荐使用typescript忽略。
请慎用@ts-nocheck,之前因为方便,直接使用了忽略全文,导致调试时,很多语法问题没有修改回来。
我们给所有@Extend
上面标注上// @ts-ignore
- 块样式
- 块内文字样式
注意:
- @Extend装饰器方法是无法定义默认参数的
- @Extend装饰器不能在struct中使用
定义固定块数据
@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
简单块样式相关数据:
- 文字内容
- 文字大小
- 文字颜色
- 背景颜色
- 透明度
定义渲染固定块方法
@Builder装饰器必须在struct内使用
@Builder装饰的方法可以定义默认参数
把主要传入参数放在最前:
- 文字内容
- 背景颜色
- 透明度
- touch事件方法
定义渲染模拟块方法
定义模拟块相关状态数据
实现
布局
了解onTouch
参考HarmonyOS触摸事件:https://developer.harmonyos.com/cn/docs/documentation/doc-references/ts-universal-events-touch-0000001158261221
OpenHarmony区别
OpenHarmony对比HarmonyOS的API文档,在TouchEvent中多返回了一个target对象。
target携带了当前绑定触摸组件的基本信息,使我们实现一些能力更加便利。
TouchEvent信息示例:
触摸事件
名称 | 是否冒泡 | 功能描述 |
---|---|---|
onTouch(callback: (event?: TouchEvent) => void) | 是 | 触摸动作触发该方法调用,event参数见TouchEvent介绍。 |
TouchEvent对象说明
属性
属性名称 | 类型 | 描述 |
---|---|---|
type | TouchType | 触摸事件的类型。 |
touches | Array<TouchObject> | 全部手指信息。 |
changedTouches | Array<TouchObject> | 当前发生变化的手指信息。 |
timestamp | number | 事件时间戳。 |
target | TargetObject | 触发组件的信息,仅TouchType.Down时有信息 |
TouchObject对象说明
属性名称 | 类型 | 描述 |
---|---|---|
type | TouchType | 触摸事件的类型。 |
id | number | 手指唯一标识符。 |
screenX | number | 触摸点相对于设备屏幕左边沿的X坐标。 |
screenY | number | 触摸点相对于设备屏幕上边沿的Y坐标。 |
x | number | 触摸点相对于被触摸元素左边沿的X坐标。 |
y | number | 触摸点相对于被触摸元素上边沿的Y坐标。 |
TouchType枚举说明
名称 | 描述 |
---|---|
Down | 手指按下时触发。 |
Up | 手指抬起时触发。 |
Move | 手指按压态在屏幕上移动时触发。 |
Cancel | 触摸事件取消时触发。 |
TargetObject对象说明
属性名称 | 类型 | 描述 |
---|---|---|
area | AreaObject | 触摸到的组件区域信息 |
AreaObject对象说明
属性名称 | 类型 | 描述 |
---|---|---|
pos | 坐标对象{x,y} | 未知 |
globalPos | 坐标对象{x,y} | 组件相对于设备屏幕左上边沿的坐标 |
width | number | 组件宽度信息 |
height | number | 组件高度信息 |
实现onTouch方法
现在就让我们来实现最重要的onTouch方法啦
一个拖拽的实现会有三个阶段:
- 手指按下,对应TouchType.Down
- 手指拖动,对应TouchType.Move
- 手指松开,对应TouchType.Up
手指按下
在IDE中,获取到的坐标,组件的高宽,返回的数据类型并不是API文档中写的number
而是一个Length
类型。
Length
是一个长度类型。
名称 | 类型定义 | 描述 |
---|---|---|
Length | string | number | 用于描述尺寸单位,输入为number类型时,使用vp单位;输入为string类型时,需要显式指定像素单位,如’10px’,也可设置百分比字符串,如’100%'。 |
由于之前我们定义的数据类型为number
,所以这里我们可以使用as
类型断言,将当前数据类型断言为number
。
手指拖动
将模拟块的坐标不断更新为手指的触摸坐标。
我们希望拖动的是块的中心点,那么就要将坐标做一个偏移处理。偏移量就是:块的宽度/2,块的高度/2。
手指松开
手指松开后这个拖拽操作也终止了,那么就应该让这个模拟块消失了。
这样一个简单的拖拽就完成了,打开Previewer看看效果吧。
问题
虽然在模拟器上能很好运行,但是在开发板上出现了问题:
应用运行在开发板上时,TouchEvent内的所有值,都比应得值小了1倍,在进行拖动时,会发现位置有很大偏移。
这个问题已提交issue,希望OpenHarmony能够解决吧。
另外,由于缺少GPU支持,在开发板上会很卡。
开发板上查看
想要在开发板(3516/rk3568)上查看的小伙伴,可以将touchEvent返回数值*2就可以看到正常的效果。
又一个程序员女神。不错的文章,谢谢分享!