1# 拖拽事件 2 3拖拽事件是指在用户界面中,当用户拖动某个对象(如文件、控件或元素)时触发的一系列事件。这些事件允许开发者自定义拖拽行为,实现诸如拖放、调整位置等功能。 4 5> **说明:** 6> 7> 从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8> 9> 应用本身预置的资源文件(即应用在安装前的HAP包中已经存在的资源文件)仅支持本地应用内拖拽。 10 11ArkUI框架对以下组件实现了默认的拖拽能力,支持对数据的拖出或拖入响应。开发者也可以通过实现通用拖拽事件来自定义拖拽响应。 12 13- 默认支持拖出能力的组件(可从组件上拖出数据):[Search](ts-basic-components-search.md)、[TextInput](ts-basic-components-textinput.md)、[TextArea](ts-basic-components-textarea.md)、[RichEditor](ts-basic-components-richeditor.md)、[Text](ts-basic-components-text.md)、[Image](ts-basic-components-image.md)、<!--Del-->[FormComponent](ts-basic-components-formcomponent-sys.md)、<!--DelEnd-->[Hyperlink](ts-container-hyperlink.md),开发者可通过设置这些组件的[draggable](ts-universal-attributes-drag-drop.md#draggable)属性来控制对默认拖拽能力的使用。 14 15- 默认支持拖入能力的组件(目标组件可响应拖入数据):[Search](ts-basic-components-search.md)、[TextInput](ts-basic-components-textinput.md)、[TextArea](ts-basic-components-textarea.md)、[RichEditor](ts-basic-components-richeditor.md),开发者可通过设置这些组件的[allowDrop](ts-universal-attributes-drag-drop.md#allowdrop)属性为null来禁用对默认拖入能力的支持。 16 17<!--RP1--><!--RP1End-->其他组件需要开发者将draggable属性设置为true,并在onDragStart等接口中实现数据传输相关内容,才能正确处理拖拽。 18 19> **说明:** 20> 21> Text组件需配合[copyOption](ts-basic-components-text.md#copyoption9)一起使用,设置copyOptions为CopyOptions.InApp或者CopyOptions.LocalDevice。 22 23## onDragStart 24 25onDragStart(event: (event: DragEvent, extraParams?: string) => CustomBuilder | DragItemInfo) 26 27第一次拖拽此事件绑定的组件时,长按时间 >= 500ms,然后手指移动距离 >= 10vp,触发回调。 28 29针对默认支持拖出能力的组件,如果开发者设置了onDragStart,优先执行开发者的onDragStart,并根据执行情况决定是否使用系统默认的拖出能力,具体为: 30- 如果开发者返回了自定义背板图,则不再使用系统默认的拖拽背板图; 31- 如果开发者设置了拖拽数据,则不再使用系统默认填充的拖拽数据。 32 33文本类组件[Text](ts-basic-components-text.md)、[Search](ts-basic-components-search.md)、[TextInput](ts-basic-components-textinput.md)、[TextArea](ts-basic-components-textarea.md)、[RichEditor](ts-basic-components-richeditor.md)对选中的文本内容进行拖拽时,不支持背板图的自定义。当onDragStart与菜单预览一起使用或使用了默认支持拖出能力的组件时,预览及菜单项上的自定义内容不支持拖拽。 34 35**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 36 37**事件优先级:** 长按触发时间 < 500ms,长按事件优先拖拽事件响应,长按触发时间 >= 500ms,拖拽事件优先长按事件响应。 38 39**系统能力:** SystemCapability.ArkUI.ArkUI.Full 40 41**参数:** 42 43| 参数名 | 类型 | 必填 | 说明 | 44| ----------- | ------------------------------- | ---- | ------------------ | 45| event | (event: [DragEvent](#dragevent7), extraParams?: string) => [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo说明) | 是 | 回调函数。<br/> **说明:**<br/> event为拖拽事件信息。<br/> extraParams为拖拽事件额外信息。需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 46 47**返回值:** 48 49| 类型 | 说明 | 50| ------------------------------------------------------------ | ------------------------ | 51| [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo说明) | 拽过程中显示的组件信息。<br/>**说明:** 不支持全局builder。 | 52 53## onDragEnter 54 55onDragEnter(event: (event: DragEvent, extraParams?: string) => void) 56 57拖拽进入组件范围内时,触发回调,当监听了[onDrop](#ondrop)事件时,此事件才有效。 58 59**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 60 61**系统能力:** SystemCapability.ArkUI.ArkUI.Full 62 63**参数:** 64 65| 参数名 | 类型 | 必填 | 说明 | 66| ----------- | ------------------------------- | ---- | ------------------------------ | 67| event | (event: [DragEvent](#dragevent7), extraParams?: string) => void | 是 | 回调函数。<br/>**说明:**<br/> event为拖拽事件信息,包括拖拽点坐标。<br/> extraParams为拖拽事件额外信息,需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 68 69## onDragMove 70 71onDragMove(event: (event: DragEvent, extraParams?: string) => void) 72 73拖拽在组件范围内移动时,触发回调,当监听了[onDrop](#ondrop)事件时,此事件才有效。 74 75**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 76 77**系统能力:** SystemCapability.ArkUI.ArkUI.Full 78 79**参数:** 80 81| 参数名 | 类型 | 必填 | 说明 | 82| ----------- | ------------------------------- | ---- | ------------------------------ | 83| event | (event: [DragEvent](#dragevent7), extraParams?: string) => void | 是 | 回调函数。<br/>**说明:**<br/> event为拖拽事件信息,包括拖拽点坐标。<br/> extraParams为拖拽事件额外信息,需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 84 85## onDragLeave 86 87onDragLeave(event: (event: DragEvent, extraParams?: string) => void) 88 89拖拽离开组件范围内时,触发回调,当监听了[onDrop](#ondrop)事件时,此事件才有效。 90 91**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 92 93**系统能力:** SystemCapability.ArkUI.ArkUI.Full 94 95**参数:** 96 97| 参数名 | 类型 | 必填 | 说明 | 98| ----------- | ------------------------------- | ---- | ------------------------------ | 99| event | (event: [DragEvent](#dragevent7), extraParams?: string) => void | 是 | 回调函数。<br/>**说明:**<br/> event为拖拽事件信息,包括拖拽点坐标。<br/> extraParams为拖拽事件额外信息,需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 100 101## onDrop 102 103onDrop(event: (event: DragEvent, extraParams?: string) => void) 104 105绑定此事件的组件可作为释放目标。当在本组件范围内停止拖放行为时,将触发回调。如果开发者未在onDrop中主动调用event.setResult()来设置拖拽接收的结果,对于系统支持的默认可拖入组件,处理结果将依据系统实际处理的数据。对于其他组件,系统将默认视为数据接收成功。 106 107**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 108 109**系统能力:** SystemCapability.ArkUI.ArkUI.Full 110 111**参数:** 112 113| 参数名 | 类型 | 必填 | 说明 | 114| ----------- | ------------------------------- | ---- | ------------------------------ | 115| event | (event: [DragEvent](#dragevent7), extraParams?: string) => void | 是 | 回调函数。<br/>**说明:**<br/> event为拖拽事件信息,包括拖拽点坐标。<br/> extraParams为拖拽事件额外信息,需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 116 117## onDrop<sup>15+</sup> 118 119onDrop(eventCallback: OnDragEventCallback, dropOptions?: DropOptions) 120 121绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。如果开发者没有在onDrop中主动调用event.setResult()设置拖拽接收的结果,若拖拽组件为系统支持默认拖入的组件,以系统实际处理数据结果为准,其它组件则系统按照数据接收成功处理。 122 123**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 124 125**系统能力:** SystemCapability.ArkUI.ArkUI.Full 126 127**参数:** 128 129| 参数名 | 类型 | 必填 | 说明 | 130| ----------- | ------------------------------- | ---- | ------------------------------ | 131| eventCallback | (event: DragEvent, extraParams?: string) => void | 是 | 回调函数。<br/>**说明:**<br/> event为拖拽事件信息,包括拖拽点坐标。<br/> extraParams为拖拽事件额外信息,需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 132| dropOptions | bool | 否 | 设置拖拽是否提前获取数据。<br/>**说明:**<br/> 当使用startDataLoading获取数据时需设置该参数为true,防止拖拽提前获取数据。 | 133 134## onDragEnd<sup>10+</sup> 135 136onDragEnd(event: (event: DragEvent, extraParams?: string) => void) 137 138绑定此事件的组件触发的拖拽结束后,触发回调。 139 140**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 141 142**系统能力:** SystemCapability.ArkUI.ArkUI.Full 143 144**参数:** 145 146| 参数名 | 类型 | 必填 | 说明 | 147| ----------- | ------------------------------- | ---- | ------------------------------ | 148| event | (event: [DragEvent](#dragevent7), extraParams?: string) => void | 是 | 回调函数。<br/>**说明:**<br/> event为拖拽事件信息,不包括拖拽点坐标。<br/> extraParams为拖拽事件额外信息,需要解析为Json格式,参考[extraParams](#extraparams说明)说明。| 149 150## onPreDrag<sup>12+</sup> 151 152onPreDrag(event: (preDragStatus: PreDragStatus) => void) 153 154绑定此事件的组件,当触发拖拽发起前的不同阶段时,触发回调。 155 156**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 157 158**系统能力:** SystemCapability.ArkUI.ArkUI.Full 159 160**参数:** 161 162| 参数名 | 类型 | 必填 | 说明 | 163| ----------- | ------------------------------- | ---- | ------------------------------ | 164| callback | Callback<(preDragStatus: [PreDragStatus](#predragstatus12枚举说明)> ) => void | 是 | 回调函数。| 165 166## DragItemInfo说明 167 168**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 169 170**系统能力:** SystemCapability.ArkUI.ArkUI.Full 171 172| 名称 | 类型 | 必填 | 描述 | 173| --------- | ---------------------------------------- | ---- | --------------------------------- | 174| pixelMap | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7) | 否 | 设置拖拽过程中显示的图片。 | 175| builder | [CustomBuilder](ts-types.md#custombuilder8) | 否 | 拖拽过程中显示自定义组件,如果设置了pixelMap,则忽略此值。<br /> **说明:** <br/>不支持全局builder。如果builder中使用了[Image](ts-basic-components-image.md)组件,应尽量开启同步加载,即配置Image的[syncLoad](ts-basic-components-image.md#syncload8)为true。该builder只用于生成当次拖拽中显示的图片,builder的修改不会同步到当前正在拖拽的图片,对builder的修改需要在下一次拖拽时生效。| 176| extraInfo | string | 否 | 拖拽项的描述。 | 177 178## PreviewConfiguration<sup>15+</sup> 179 180配置自定义拖拽过程中的预览图样式。 181 182**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 183 184**系统能力:** SystemCapability.ArkUI.ArkUI.Full 185 186| 名称 | 类型 | 只读 | 可选 | 说明 | 187| ---------- | ---- | ---- | ---- | ------------------------------------------------------------ | 188| onlyForLifting | boolean | 否 | 是 | 自定义配置的预览图是否仅用于浮起。<br /> **说明:** <br/>默认值为false。设置为true时,如果发起长按拖拽,浮起时的跟手图为自定义配置的预览图,拖拽时的跟手图不使用[dragPreview](ts-universal-attributes-drag-drop.md#dragpreview11)属性,优先使用开发者在[onDragStart](ts-universal-events-drag-drop.md#ondragstart)中返回的背板图,如果[onDragStart](ts-universal-events-drag-drop.md#ondragstart)中没有返回背板图则使用组件自截图。| 189| delayCreating | boolean | 否 | 是 | 组件预览builder是否在设置时加载。<br/>默认值为false。| 190 191## extraParams说明 192 193 用于返回组件在拖拽中需要用到的额外信息。 194 195 extraParams是Json对象转换的string字符串,可以通过Json.parse转换的Json对象获取如下属性。 196 197| 名称 | 类型 | 描述 | 198| ------------- | ------ | ---------------------------------------- | 199| selectedIndex | number | 当拖拽事件设在父容器的子元素时,selectedIndex表示当前被拖拽子元素是父容器第selectedIndex个子元素,selectedIndex从0开始。<br/>仅在ListItem组件的拖拽事件中生效。 | 200| insertIndex | number | 当前拖拽元素在List组件中放下时,insertIndex表示被拖拽元素插入该组件的第insertIndex个位置,insertIndex从0开始。<br/>仅在List组件的拖拽事件中生效。 | 201 202## DragEvent<sup>7+</sup> 203 204**系统能力:** SystemCapability.ArkUI.ArkUI.Full 205 206### 属性 207 208**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 209 210**系统能力:** SystemCapability.ArkUI.ArkUI.Full 211 212| 名称 | 类型 | 描述 | 213| ------ | ------ | ---------------- | 214| useCustomDropAnimation<sup>10+</sup> | boolean | 当拖拽结束时,是否禁用系统默认落位动效。<br/>应用可将该值设定为true来禁用系统默认落位动效,并实现自己的自定义落位动效。<br/>当不配置或设置为false时,系统默认落位动效生效,当松手位置的控件可接收拖拽的数据时,落位为缩小消失动效,若不可接收数据,则为放大消失动效。<br/>当未禁用系统默认落位动效情况下,应用不应再实现自定义动效,以避免动效上的冲突。| 215|dragBehavior<sup>10+</sup> | [DragBehavior](#dragbehavior10) | 切换复制和剪贴模式的角标显示状态。 | 216 217### 方法 218 219**系统能力:** SystemCapability.ArkUI.ArkUI.Full 220 221| 名称 | 返回值类型 | 描述 | 222| ----------- | ------------------------------- | ------------------------------ | 223| setData(unifiedData: [UnifiedData](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata))<sup>10+</sup> | void | 向DragEvent中设置拖拽相关数据。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 224| getData()<sup>10+</sup> | [UnifiedData](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata) | 从DragEvent中获取拖拽相关数据。数据获取结果请参考错误码说明。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 225| getSummary()<sup>10+</sup> | [Summary](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#summary) | 从DragEvent中获取拖拽相关数据的简介。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 226| setResult(dragRect: [DragResult](#dragresult10枚举说明))<sup>10+</sup> | void | 向DragEvent中设置拖拽结果。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 227| getResult()<sup>10+</sup> | [DragResult](#dragresult10枚举说明) | 从DragEvent中获取拖拽结果。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 228| getPreviewRect()<sup>10+</sup> | [Rectangle](ts-universal-attributes-touch-target.md#rectangle对象说明) | 获取拖拽跟手图相对于当前窗口的位置,以及跟手图尺寸信息,单位VP,其中x和y代表跟手图左上角的窗口坐标,width和height代表跟手图的尺寸。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 229| getVelocityX()<sup>10+</sup> | number | 获取当前拖拽的x轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从左往右为正,反之为负。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 230| getVelocityY()<sup>10+</sup> | number | 获取当前拖拽的y轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从上往下为正,反之为负。 | 231| getVelocity()<sup>10+</sup> | number | 获取当前拖拽的主方向拖动速度。为xy轴方向速度的平方和的算术平方根。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 232| getWindowX()<sup>10+</sup> | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 233| getWindowY()<sup>10+</sup> | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 234| getDisplayX()<sup>10+</sup> | number | 当前拖拽点相对于屏幕左上角的x轴坐标,单位为vp。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 235| getDisplayY()<sup>10+</sup> | number | 当前拖拽点相对于屏幕左上角的y轴坐标,单位为vp。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 236| getModifierKeyState<sup>12+</sup> | (Array<string>) => bool | 获取功能键按压状态。报错信息请参考以下错误码。支持功能键 'Ctrl'\|'Alt'\|'Shift'\|'Fn',设备外接带Fn键的键盘不支持Fn键查询。 <br/>**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。| 237| startDataLoading(options: [DataSyncOptions](#datasyncoptions15))<sup>15+</sup> | string | 异步获取拖拽数据,并通知开发者当前数据同步进度,仅支持在onDrop阶段使用。数据传输过程中可使用[cancelDataLoading](../js-apis-arkui-UIContext.md#canceldataloading15)接口取消。<br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 | 238| getX()<sup>(deprecated)</sup> | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。<br>从API Version 10开始不再维护,建议使用getWindowX()代替。 | 239| getY()<sup>(deprecated)</sup> | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。<br>从API Version 10开始不再维护,建议使用getWindowY()代替。 | 240 241 242**错误码:** 243 244以下错误码的详细介绍请参见[通用错误码](../../errorcode-universal.md)和[drag-event(拖拽事件)](../errorcode-drag-event.md)错误码。 245 246| 错误码ID | 错误信息 | 247| --------- | ------- | 248| 401 | Parameter error. Possible causes: 1. Incorrect parameter types. 2. Parameter verification failed. | 249| 190001 | Data not found.| 250| 190002 | Data error. | 251| 190003 | Operation on allowed for current pharse. | 252 253## DragResult<sup>10+</sup>枚举说明 254 255**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 256 257**系统能力:** SystemCapability.ArkUI.ArkUI.Full 258 259| 名称 | 描述 | 260| ----- | ----------------- | 261| DRAG_SUCCESSFUL | 拖拽成功,在onDrop中使用。 | 262| DRAG_FAILED | 拖拽失败,在onDrop中使用。 | 263| DRAG_CANCELED | 拖拽取消,在onDrop中使用。 | 264| DROP_ENABLED | 组件允许落入,在onDragMove中使用。 | 265| DROP_DISABLED | 组件不允许落入,在onDragMove中使用。 | 266 267## DragBehavior<sup>10+</sup> 268 269当设置[DragResult](#dragresult10枚举说明)为DROP_ENABLED后,可设置DragBehavior为复制(COPY)或剪切(MOVE)。DragBehavior用来向开发者描述数据的处理方式是复制(COPY)还是剪切(MOVE),但无法最终决定对数据的实际处理方式。DragBehavior会通过onDragEnd带回给数据拖出方,发起拖拽的一方可通过DragBehavior来区分做出的是复制还是剪切数据的不同行为。 270 271**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 272 273**系统能力:** SystemCapability.ArkUI.ArkUI.Full 274 275| 名称 | 描述 | 276| ----- | ----------------- | 277| COPY | 指定对数据的处理方式为复制。| 278| MOVE| 指定对数据的处理方式为剪切。| 279 280## PreDragStatus<sup>12+</sup>枚举说明 281 282**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 283 284**系统能力:** SystemCapability.ArkUI.ArkUI.Full 285 286| 名称 | 值 | 描述 | 287| ---- | - | ----------------- | 288| ACTION_DETECTING_STATUS | 0 | 拖拽手势启动阶段。(按下50ms时触发) | 289| READY_TO_TRIGGER_DRAG_ACTION | 1 | 拖拽准备完成,可发起拖拽阶段。(按下500ms时触发) | 290| PREVIEW_LIFT_STARTED | 2 | 拖拽浮起动效发起阶段。(按下800ms时触发) | 291| PREVIEW_LIFT_FINISHED | 3 | 拖拽浮起动效结束阶段。(浮起动效完全结束时触发) | 292| PREVIEW_LANDING_STARTED | 4 | 拖拽落回动效发起阶段。(落回动效发起时触发) | 293| PREVIEW_LANDING_FINISHED | 5 | 拖拽落回动效结束阶段。(落回动效结束时触发) | 294| ACTION_CANCELED_BEFORE_DRAG | 6 | 拖拽浮起落位动效中断。(已满足READY_TO_TRIGGER_DRAG_ACTION状态后,未达到动效阶段,手指抬手时触发) | 295| PREPARING_FOR_DRAG_DETECTION<sup>18+</sup> | 7 | 拖拽准备完成,可发起拖拽阶段。(按下350ms时触发) | 296 297## executeDropAnimation<sup>18+</sup> 298 299设置一个自定义落位动效的执行函数,仅在useCustomDropAnimation为true时有效。 300 301**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 302 303**系统能力:** SystemCapability.ArkUI.ArkUI.Full 304 305| 参数名 | 类型 | 描述 | 306| ------ | ------ | ---------------- | 307| customDropAnimation | Callback\<void\> | 在独立的接口中实现自定义落位动效。<br/> **说明:** <br/>1. 该接口仅在 onDrop 回调中使用有效。<br/> 2. 使用前需设置 useCustomDropAnimation 为 true,否则该接口不生效。<br/> 3. 不要在动画callback中实现与动效无关的逻辑,避免影响执行效率。| 308 309## DataSyncOptions<sup>15+</sup> 310 311type DataSyncOptions = GetDataParams 312 313作为startDataLoading的入参对象 314 315**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 316 317**系统能力:** SystemCapability.ArkUI.ArkUI.Full 318 319| 类型 | 说明 | 320| ----- | ----------------- | 321| [GetDataParams](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#getdataparams15) | 表示从UDMF获取数据时的参数,包含目标路径、文件冲突选项、进度条类型等。| 322 323## 示例 324 325### 示例1(设置组件拖拽和落入) 326 327该示例展示了部分组件(如Image和Text等)拖拽和可落入区域的设置。 328 329```ts 330// xxx.ets 331import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; 332import { promptAction } from '@kit.ArkUI'; 333import { BusinessError } from '@kit.BasicServicesKit'; 334 335@Entry 336@Component 337struct Index { 338 @State targetImage: string = ''; 339 @State targetText: string = 'Drag Text'; 340 @State imageWidth: number = 100; 341 @State imageHeight: number = 100; 342 @State imgState: Visibility = Visibility.Visible; 343 @State abstractContent: string = "abstract"; 344 @State textContent: string = ""; 345 @State backGroundColor: Color = Color.Transparent; 346 347 @Builder 348 pixelMapBuilder() { 349 Column() { 350 Image($r('app.media.icon')) 351 .width(120) 352 .height(120) 353 .backgroundColor(Color.Yellow) 354 } 355 } 356 357 getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) { 358 try { 359 let data: UnifiedData = event.getData(); 360 if (!data) { 361 return false; 362 } 363 let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords(); 364 if (!records || records.length <= 0) { 365 return false; 366 } 367 callback(event); 368 return true; 369 } catch (e) { 370 console.log("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message); 371 return false; 372 } 373 } 374 375 getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) { 376 if (this.getDataFromUdmfRetry(event, callback)) { 377 return; 378 } 379 setTimeout(() => { 380 this.getDataFromUdmfRetry(event, callback); 381 }, 1500); 382 } 383 384 private PreDragChange(preDragStatus: PreDragStatus): void { 385 if (preDragStatus == PreDragStatus.READY_TO_TRIGGER_DRAG_ACTION) { 386 this.backGroundColor = Color.Red; 387 } else if (preDragStatus == PreDragStatus.ACTION_CANCELED_BEFORE_DRAG 388 || preDragStatus == PreDragStatus.PREVIEW_LANDING_FINISHED) { 389 this.backGroundColor = Color.Blue; 390 } 391 } 392 393 build() { 394 Row() { 395 Column() { 396 Text('start Drag') 397 .fontSize(18) 398 .width('100%') 399 .height(40) 400 .margin(10) 401 .backgroundColor('#008888') 402 Image($r('app.media.icon')) 403 .width(100) 404 .height(100) 405 .draggable(true) 406 .margin({ left: 15 }) 407 .visibility(this.imgState) 408 .onDragEnd((event) => { 409 // onDragEnd里取到的result值在接收方onDrop设置 410 if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { 411 this.getUIContext().getPromptAction().showToast({ duration: 100, message: 'Drag Success' }); 412 } else if (event.getResult() === DragResult.DRAG_FAILED) { 413 this.getUIContext().getPromptAction().showToast({ duration: 100, message: 'Drag failed' }); 414 } 415 }) 416 Text('test drag event') 417 .width('100%') 418 .height(100) 419 .draggable(true) 420 .margin({ left: 15 }) 421 .copyOption(CopyOptions.InApp) 422 TextArea({ placeholder: 'please input words' }) 423 .copyOption(CopyOptions.InApp) 424 .width('100%') 425 .height(50) 426 .draggable(true) 427 Search({ placeholder: 'please input you word' }) 428 .searchButton('Search') 429 .width('100%') 430 .height(80) 431 .textFont({ size: 20 }) 432 433 Column() { 434 Text('this is abstract') 435 .fontSize(20) 436 .width('100%') 437 }.margin({ left: 40, top: 20 }) 438 .width('100%') 439 .height(100) 440 .onDragStart((event) => { 441 this.backGroundColor = Color.Transparent; 442 let data: unifiedDataChannel.PlainText = new unifiedDataChannel.PlainText(); 443 data.abstract = 'this is abstract'; 444 data.textContent = 'this is content this is content'; 445 (event as DragEvent).setData(new unifiedDataChannel.UnifiedData(data)); 446 }) 447 .onPreDrag((status: PreDragStatus) => { 448 this.PreDragChange(status); 449 }) 450 .backgroundColor(this.backGroundColor) 451 }.width('45%') 452 .height('100%') 453 454 Column() { 455 Text('Drag Target Area') 456 .fontSize(20) 457 .width('100%') 458 .height(40) 459 .margin(10) 460 .backgroundColor('#008888') 461 Image(this.targetImage) 462 .width(this.imageWidth) 463 .height(this.imageHeight) 464 .draggable(true) 465 .margin({ left: 15 }) 466 .border({ color: Color.Black, width: 1 }) 467 .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) 468 .onDrop((dragEvent?: DragEvent) => { 469 this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => { 470 let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords(); 471 let rect: Rectangle = event.getPreviewRect(); 472 this.imageWidth = Number(rect.width); 473 this.imageHeight = Number(rect.height); 474 this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri; 475 event.useCustomDropAnimation = false; 476 this.imgState = Visibility.None; 477 // 显式设置result为successful,则将该值传递给拖出方的onDragEnd 478 event.setResult(DragResult.DRAG_SUCCESSFUL); 479 }) 480 }) 481 482 Text(this.targetText) 483 .width('100%') 484 .height(100) 485 .border({ color: Color.Black, width: 1 }) 486 .margin(15) 487 .allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT]) 488 .onDrop((dragEvent?: DragEvent) => { 489 this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => { 490 let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords(); 491 let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText; 492 this.targetText = plainText.textContent; 493 }) 494 }) 495 496 Column() { 497 Text(this.abstractContent).fontSize(20).width('100%') 498 Text(this.textContent).fontSize(15).width('100%') 499 } 500 .width('100%') 501 .height(100) 502 .margin(20) 503 .border({ color: Color.Black, width: 1 }) 504 .allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT]) 505 .onDrop((dragEvent?: DragEvent) => { 506 this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => { 507 let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords(); 508 let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText; 509 this.abstractContent = plainText.abstract as string; 510 this.textContent = plainText.textContent; 511 }) 512 }) 513 }.width('45%') 514 .height('100%') 515 .margin({ left: '5%' }) 516 } 517 .height('100%') 518 } 519} 520``` 521 522 523### 示例2(自定义落位动效) 524 525通过自定义接口executeDropAnimation,实现落位动效。 526```ts 527import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; 528 529@Entry 530@Component 531struct DropAnimationExample { 532 @State targetImage: string = ''; 533 @State targetText: string = 'Drag Text'; 534 @State hyperLinkText: string = 'HyperLink'; 535 @State hyperLinkContent: string = 'HyperLink'; 536 @State imageWidth: number = 100; 537 @State imageHeight: number = 100; 538 @State imgState: Visibility = Visibility.Visible; 539 @State videoSrc: string = 'resource://RAWFILE/02.mp4'; 540 @State abstractContent: string = "abstract"; 541 @State textContent: string = ""; 542 543 customDropAnimation = 544 () => { 545 this.getUIContext().animateTo({ duration: 1000, curve: Curve.EaseOut, playMode: PlayMode.Normal }, () => { 546 this.imageWidth = 200; 547 this.imageHeight = 200; 548 this.imgState = Visibility.None; 549 }) 550 } 551 552 build() { 553 Row() { 554 Column() { 555 Image($r('app.media.app_icon')) 556 .width(100) 557 .height(100) 558 .draggable(true) 559 .margin({ left: 15 ,top: 40}) 560 .visibility(this.imgState) 561 .onDragStart((event) => { 562 }) 563 .onDragEnd((event) => { 564 if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { 565 console.info('Drag Success'); 566 } else if (event.getResult() === DragResult.DRAG_FAILED) { 567 console.error('Drag failed'); 568 } 569 }) 570 }.width('45%') 571 .height('100%') 572 Column() { 573 Text('Drag Target Area') 574 .fontSize(20) 575 .width(180) 576 .height(40) 577 .textAlign(TextAlign.Center) 578 .margin(10) 579 .backgroundColor('rgb(240,250,255)') 580 Column() { 581 Image(this.targetImage) 582 .width(this.imageWidth) 583 .height(this.imageHeight) 584 } 585 .draggable(true) 586 .margin({ left: 15 }) 587 .border({ color: Color.Black, width: 1 }) 588 .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) 589 .onDrop((dragEvent: DragEvent) => { 590 let records: Array<unifiedDataChannel.UnifiedRecord> = dragEvent.getData().getRecords(); 591 let rect: Rectangle = dragEvent.getPreviewRect(); 592 this.imageWidth = Number(rect.width); 593 this.imageHeight = Number(rect.height); 594 this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri; 595 dragEvent.useCustomDropAnimation = true; 596 dragEvent.executeDropAnimation(this.customDropAnimation) 597 }) 598 .width(this.imageWidth) 599 .height(this.imageHeight) 600 }.width('45%') 601 .height('100%') 602 .margin({ left: '5%' }) 603 } 604 .height('100%') 605 } 606} 607``` 608 609 610### 示例3(拖拽异步获取数据) 611 612通过startDataLoading实现拖拽异步获取数据。 613 614```ts 615import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; 616import { fileUri, fileIo as fs } from '@kit.CoreFileKit' 617import { common } from '@kit.AbilityKit' 618 619@Entry 620@Component 621struct ImageExample { 622 @State uri: string = ""; 623 @State blockArr: string[] = []; 624 uiContext = this.getUIContext(); 625 udKey: string = ''; 626 627 build() { 628 Column() { 629 Text('Image拖拽') 630 .fontSize('30dp') 631 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceAround }) { 632 Image($r('app.media.startIcon')) 633 .width(100) 634 .height(100) 635 .border({ width: 1 }) 636 .draggable(true) 637 .onDragStart((event:DragEvent) => { 638 const context: Context|undefined = this.uiContext.getHostContext(); 639 if(context) { 640 let data = context.resourceManager.getMediaContentSync($r('app.media.startIcon').id, 120); 641 const arrayBuffer: ArrayBuffer = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset); 642 let filePath = context.filesDir + '/test.png'; 643 let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); 644 fs.writeSync(file.fd, arrayBuffer); 645 //获取图片的uri 646 let uri = fileUri.getUriFromPath(filePath); 647 let image: unifiedDataChannel.Image = new unifiedDataChannel.Image(); 648 image.imageUri = uri; 649 let dragData: unifiedDataChannel.UnifiedData = new unifiedDataChannel.UnifiedData(image); 650 (event as DragEvent).setData(dragData); 651 } 652 }) 653 } 654 .margin({ bottom: 20 }) 655 Row() { 656 Column(){ 657 Text('可释放区域') 658 .fontSize('15dp') 659 .height('10%') 660 List(){ 661 ForEach(this.blockArr, (item:string, index) => { 662 ListItem() { 663 Image(item) 664 .width(100) 665 .height(100) 666 .border({width: 1}) 667 } 668 .margin({ left: 30 , top : 30}) 669 }, (item:string) => item) 670 } 671 .border({width: 1}) 672 .height('90%') 673 .width('100%') 674 .onDrop((event?: DragEvent, extraParams?: string) => { 675 console.log("enter onDrop") 676 let context = this.uiContext.getHostContext() as common.UIAbilityContext; 677 let pathDir: string = context.distributedFilesDir; 678 let destUri = fileUri.getUriFromPath(pathDir); 679 let progressListener: unifiedDataChannel.DataProgressListener = (progress: unifiedDataChannel.ProgressInfo, dragData: UnifiedData|null) => { 680 if(dragData != null) { 681 let arr:Array<unifiedDataChannel.UnifiedRecord> = dragData.getRecords(); 682 if(arr.length > 0) { 683 if (arr[0].getType() === uniformTypeDescriptor.UniformDataType.IMAGE) { 684 let image = arr[0] as unifiedDataChannel.Image; 685 this.uri = image.imageUri; 686 this.blockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri); 687 } 688 } else { 689 console.log('dragData arr is null'); 690 } 691 } else { 692 console.log('dragData is undefined'); 693 } 694 console.log(`percentage: ${progress.progress}`); 695 }; 696 let options: DataSyncOptions = { 697 destUri: destUri, 698 fileConflictOptions: unifiedDataChannel.FileConflictOptions.OVERWRITE, 699 progressIndicator: unifiedDataChannel.ProgressIndicator.DEFAULT, 700 dataProgressListener: progressListener, 701 } 702 try { 703 this.udKey = (event as DragEvent).startDataLoading(options); 704 console.log('udKey: ', this.udKey); 705 } catch(e) { 706 console.log(`startDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`); 707 } 708 }, {disableDataPrefetch: true}) 709 } 710 .height("50%") 711 .width("90%") 712 .border({ width: 1 }) 713 } 714 Button('取消数据传输') 715 .onClick(() => { 716 try { 717 this.getUIContext().getDragController().cancelDataLoading(this.udKey); 718 } catch (e) { 719 console.log(`cancelDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`); 720 } 721 }) 722 .margin({top: 10}) 723 }.width('100%') 724 } 725} 726```