• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Drag Event
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @jiangtao92-->
5<!--Designer: @piggyguy-->
6<!--Tester: @songyanhong-->
7<!--Adviser: @HelloCrease-->
8
9A drag event refers to a sequence of events triggered in the UI when a user drags an object (such as a file, component, or element). These events allow you to customize drag and drop behaviors, enabling functionalities like drag and drop operations and position adjustments.
10
11>  **NOTE**
12>
13>  The initial APIs of this module are supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version.
14>
15> The resource files preset in the application (that is, the resource files that are contained in the HAP file before the application is installed) can be dragged and dropped only within the application.
16
17The ArkUI framework provides default drag and drop capabilities for the following components, allowing them to serve as the drag source (from which data can be dragged) or drop target (to which data can be dropped). You can further customize drag and drop behavior by implementing universal drag events.
18
19- The following component supports drag actions by default: [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), [Hyperlink](ts-container-hyperlink.md). You can control the default drag behavior by setting the [draggable](ts-universal-attributes-drag-drop.md#draggable) attribute.
20
21- The following component supports drop actions by default: [Search](ts-basic-components-search.md), [TextInput](ts-basic-components-textinput.md), [TextArea](ts-basic-components-textarea.md), [RichEditor](ts-basic-components-richeditor.md). You can disable the default drag behavior by setting the [allowDrop](ts-universal-attributes-drag-drop.md#allowdrop) attribute to **null**.
22
23To enable drag and drop for other components, you need to set the **draggable** attribute to **true** and implement data transmission in APIs such as [onDragStart](ts-universal-events-drag-drop.md#ondragstart).
24<!--RP1--><!--RP1End-->
25
26> **NOTE**
27>
28> When using the **Text** component, set [copyOption](ts-basic-components-text.md#copyoption9) to **CopyOptions.InApp** or **CopyOptions.LocalDevice**.
29
30## onDragStart
31
32onDragStart(event: (event: DragEvent, extraParams?: string) => CustomBuilder | DragItemInfo): T
33
34Triggered when the component bound to the event is dragged for the first time. A drag operation is recognized only when the long press time is 500 ms or longer and the dragging distance is 10 vp or larger.
35
36For components that can serve as the drag source by default, a custom **onDragStart** event, if set, is executed and:
37- If a custom drag preview is returned, it is used in place of the default drag preview.
38- If drag data is set, it is used in place of the default drag data.
39
40No custom drag preview is supported for dragging selected text in the following components: [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) When **onDragStart** is used together with menu preview or any component that can serve as the drag source by default is used, custom content on menu items and the preview cannot be dragged.
41
42**Atomic service API**: This API can be used in atomic services since API version 11.
43
44**Event priority**:<br>Long press time < 500 ms: Long press event > Drag event<br>Other cases: Drag event > Long press event
45
46**System capability**: SystemCapability.ArkUI.ArkUI.Full
47
48**Parameters**
49
50| Name     | Type                           | Mandatory| Description              |
51| ----------- | ------------------------------- | ---- | ------------------ |
52| event    | (event: [DragEvent](#dragevent7), extraParams?: string) => [CustomBuilder](ts-types.md#custombuilder8)  \|  [DragItemInfo](#dragiteminfo)  | Yes  | Callback function.<br> **NOTE**<br> **event**: information about the drag event.<br> **extraParams**: extra information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).<br> **CustomBuilder**: component information displayed during dragging. Global builders are not supported.|
53
54**Return value**
55
56| Type| Description|
57| -------- | -------- |
58| T | Current component.|
59
60## onDragEnter
61
62onDragEnter(event: (event: DragEvent, extraParams?: string) => void): T
63
64Triggered when a dragged item enters a valid drop target. This event takes effect only when a listener for the [onDrop](#ondrop) event is enabled.
65
66**Atomic service API**: This API can be used in atomic services since API version 11.
67
68**System capability**: SystemCapability.ArkUI.ArkUI.Full
69
70**Parameters**
71
72| Name     | Type                           | Mandatory| Description                          |
73| ----------- | ------------------------------- | ---- | ------------------------------ |
74| event    | (event: [DragEvent](#dragevent7), extraParams?: string) => void   | Yes  | Callback function.<br>**NOTE**<br> **event**: information about the drag event, including the coordinates of the item that is being dragged.<br> **extraParams**: additional information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).|
75
76**Return value**
77
78| Type| Description|
79| -------- | -------- |
80| T | Current component.|
81
82## onDragMove
83
84onDragMove(event: (event: DragEvent, extraParams?: string) => void): T
85
86Triggered when a dragged item moves in a valid drop target. This event takes effect only when a listener for the [onDrop](#ondrop) event is enabled.
87
88**Atomic service API**: This API can be used in atomic services since API version 11.
89
90**System capability**: SystemCapability.ArkUI.ArkUI.Full
91
92**Parameters**
93
94| Name     | Type                           | Mandatory| Description                          |
95| ----------- | ------------------------------- | ---- | ------------------------------ |
96| event    | (event: [DragEvent](#dragevent7), extraParams?: string) => void   | Yes  | Callback function.<br>**NOTE**<br> **event**: information about the drag event, including the coordinates of the item that is being dragged.<br> **extraParams**: additional information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).|
97
98**Return value**
99
100| Type| Description|
101| -------- | -------- |
102| T | Current component.|
103
104## onDragLeave
105
106onDragLeave(event: (event: DragEvent, extraParams?: string) => void): T
107
108Triggered when a dragged item leaves a valid drop target. This event takes effect only when a listener for the [onDrop](#ondrop) event is enabled.
109
110**Atomic service API**: This API can be used in atomic services since API version 11.
111
112**System capability**: SystemCapability.ArkUI.ArkUI.Full
113
114**Parameters**
115
116| Name     | Type                           | Mandatory| Description                          |
117| ----------- | ------------------------------- | ---- | ------------------------------ |
118| event    | (event: [DragEvent](#dragevent7), extraParams?: string) => void   | Yes  | Callback function.<br>**NOTE**<br> **event**: information about the drag event, including the coordinates of the item that is being dragged.<br> **extraParams**: additional information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).|
119
120**Return value**
121
122| Type| Description|
123| -------- | -------- |
124| T | Current component.|
125
126## onDrop
127
128onDrop(event: (event: DragEvent, extraParams?: string) => void): T
129
130Triggered when a drag operation ends within the bounds of the component bound to this event. If **event.setResult()** is not explicitly called in the **onDrop** callback to set the drag-and-drop result, then: For supported components, the result is determined based on the actual data processed; for other components, the system considers the data as successfully received.
131
132**Atomic service API**: This API can be used in atomic services since API version 11.
133
134**System capability**: SystemCapability.ArkUI.ArkUI.Full
135
136**Parameters**
137
138| Name     | Type                           | Mandatory| Description                          |
139| ----------- | ------------------------------- | ---- | ------------------------------ |
140| event    | (event: [DragEvent](#dragevent7), extraParams?: string) => void   | Yes  | Callback function.<br>**NOTE**<br> **event**: information about the drag event, including the coordinates of the item that is being dragged.<br> **extraParams**: additional information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).|
141
142**Return value**
143
144| Type| Description|
145| -------- | -------- |
146| T | Current component.|
147
148## onDrop<sup>15+</sup>
149
150onDrop(eventCallback: OnDragEventCallback, dropOptions?: DropOptions): T
151
152Triggered when a dragged item is dropped on a valid drop target. If you do not explicitly call **event.setResult()** in **onDrop** to set the result of the drag reception, the system handles it as follows:<br>- If the component being dragged is one that supports drop actions by default, the system's actual data processing result is used.<br>- For other components, the system assumes that the data is received successfully.
153
154**Atomic service API**: This API can be used in atomic services since API version 15.
155
156**System capability**: SystemCapability.ArkUI.ArkUI.Full
157
158**Parameters**
159
160| Name     | Type                           | Mandatory| Description                          |
161| ----------- | ------------------------------- | ---- | ------------------------------ |
162| eventCallback  | [OnDragEventCallback](#ondrageventcallback15)   | Yes  | Callback function.|
163| dropOptions  | [DropOptions](#dropoptions15)   | No  | Parameters for the drop process.|
164
165**Return value**
166
167| Type| Description|
168| -------- | -------- |
169| T | Current component.|
170
171## onDragEnd<sup>10+</sup>
172
173onDragEnd(event: (event: DragEvent, extraParams?: string) => void): T
174
175Triggered when the dragging of the component bound to the event ends.
176
177**Atomic service API**: This API can be used in atomic services since API version 11.
178
179**System capability**: SystemCapability.ArkUI.ArkUI.Full
180
181**Parameters**
182
183| Name     | Type                           | Mandatory| Description                          |
184| ----------- | ------------------------------- | ---- | ------------------------------ |
185| event    | (event: [DragEvent](#dragevent7), extraParams?: string) => void   | Yes  | Callback function.<br>**NOTE**<br> **event**: information about the drag event, excluding the coordinates of the item that is being dragged.<br> **extraParams**: additional information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).|
186
187**Return value**
188
189| Type| Description|
190| -------- | -------- |
191| T | Current component.|
192
193## onPreDrag<sup>12+</sup>
194
195onPreDrag(callback: Callback\<PreDragStatus>): T
196
197Triggered when the component enters a state prior to a drop and drop operation.
198
199**Atomic service API**: This API can be used in atomic services since API version 12.
200
201**System capability**: SystemCapability.ArkUI.ArkUI.Full
202
203**Parameters**
204
205| Name     | Type                           | Mandatory| Description                          |
206| ----------- | ------------------------------- | ---- | ------------------------------ |
207| callback    | Callback<[PreDragStatus](#predragstatus12)>     | Yes  | Callback function.|
208
209**Return value**
210
211| Type| Description|
212| -------- | -------- |
213| T | Current component.|
214
215## onDragSpringLoading<sup>20+</sup>
216
217onDragSpringLoading(callback: Callback\<SpringLoadingContext\> | null, configuration?: DragSpringLoadingConfiguration): T
218
219Triggered when a dragged item hovers over the component configured as a drag target with hover detection capability. Only one target can become the responder at any time, and child components always have higher priority.
220
221For details about the hover detection triggering mechanism and usage, see [Spring Loading (Hover Detection) Support](../../../ui/arkts-common-events-drag-event.md#spring-loading-hover-detection-support).
222
223**Atomic service API**: This API can be used in atomic services since API version 20.
224
225**System capability**: SystemCapability.ArkUI.ArkUI.Full
226
227**Parameters**
228
229| Name       | Type                                     | Mandatory| Description                                          |
230| :------------ | ----------------------------------------- | ---- | ---------------------------------------------- |
231| callback          | Callback\<[SpringLoadingContext](#springloadingcontext20)\> \| null    | Yes  | Hover detection callback. If the value is **null**, hover detection is disabled.|
232| configuration | [DragSpringLoadingConfiguration](../js-apis-arkui-dragController.md#dragspringloadingconfiguration20) | No  | Hover detection configuration. If the value is **undefined**, the default value of [DragSpringLoadingConfiguration](../js-apis-arkui-dragController.md#dragspringloadingconfiguration20) is used. |
233
234**Return value**
235
236| Type| Description|
237| -------- | -------- |
238| T | Current component.|
239
240## DragItemInfo
241
242**Atomic service API**: This API can be used in atomic services since API version 11.
243
244**System capability**: SystemCapability.ArkUI.ArkUI.Full
245
246| Name     | Type                 | Read-Only| Optional  | Description                              |
247| --------- | ---------------------------------------- | ---- | ---- | --------------------------------- |
248| pixelMap  | [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md) | No   |  Yes  |Image to be displayed during dragging.|
249| builder   | [CustomBuilder](ts-types.md#custombuilder8) | No   |  Yes  |Custom component to display during dragging. If **pixelMap** is set, this parameter is ignored.<br> **NOTE**<br>Global builder definition is not supported. If the [Image](ts-basic-components-image.md) component is used in the builder, enable synchronous loading whenever possible, that is, set the [syncLoad](ts-basic-components-image.md#syncload8) attribute of the component to **true**. The builder is used only to generate the image displayed during the current dragging. Changes to the builder, if any, apply to the next dragging, but not to the current dragging.|
250| extraInfo | string                                   | No   |  Yes  |Extra information of the dragged item.                          |
251
252## PreviewConfiguration<sup>15+</sup>
253
254Defines the preview image style during a drag operation.
255
256**Atomic service API**: This API can be used in atomic services since API version 15.
257
258**System capability**: SystemCapability.ArkUI.ArkUI.Full
259
260| Name      | Type| Read-Only| Optional| Description                                                        |
261| ---------- | ---- | ---- | ---- | ------------------------------------------------------------ |
262| onlyForLifting | boolean | No   | Yes   | Whether the custom preview image is used only for lifting.<br> **NOTE**<br>The default value is **false**. **true**: The custom preview image is used only for lifting. **false**: The custom preview image is used for both lifting and dragging. When the value is set to **true**, the preview image is used only during the lifting phase of a long press. For the preview image used during the dragging phase: The [dragPreview](ts-universal-attributes-drag-drop.md#dragpreview11) attribute is ignored, and the system prioritizes the image returned in [onDragStart](ts-universal-events-drag-drop.md#ondragstart); if no image is returned in **onDragStart**, the component's snapshot is used.|
263| delayCreating  | boolean | No   | Yes   | Whether the preview builder is loaded at the time of setting.<br>The default value is **false**. The value **true** means that the preview builder is loaded at the time of setting, and **false** means the opposite.|
264
265## extraParams
266
267  Provides additional information required for dragging an item.
268
269  **extraParams** is a string converted from a JSON object. You can obtain the following attributes using the JSON object converted from **Json.parse**.
270
271| Name         | Type  | Description                                      |
272| ------------- | ------ | ---------------------------------------- |
273| selectedIndex | number | Index of the dragged item in the parent container. The value of **selectedindex** starts from **0**.<br>This parameter takes effect only in the drag event of the **ListItem** component.|
274| insertIndex   | number | Index of the element into which the dragged item is dropped in the **List** component. The value of **insertIndex** starts from **0**.<br>This parameter takes effect only in the drag event of the **List** component.|
275
276## DragEvent<sup>7+</sup>
277
278**System capability**: SystemCapability.ArkUI.ArkUI.Full
279
280### Properties
281
282**Atomic service API**: This API can be used in atomic services since API version 11.
283
284**System capability**: SystemCapability.ArkUI.ArkUI.Full
285
286| Name    | Type | Read-Only| Optional| Description            |
287| ------ | ------ | ----- | ---- | ------- |
288| useCustomDropAnimation<sup>10+</sup> | boolean | No| No|Whether to disable the default drop animation when the dragging ends.<br>If this parameter is set to **true**, the default drop animation is disabled, and the custom one is used.<br>If this parameter is set to **false** or is not set, the default drop animation is enabled. If the drop target can accept data, it will show a shrinking disappearance animation; if not, it will show an enlarging disappearance animation.<br>When the default drop animation is not disabled, avoid implementing custom animations to prevent conflicts.|
289|dragBehavior<sup>10+</sup> | [DragBehavior](#dragbehavior10) | No| No|Copy or paste mode.|
290
291### setData<sup>10+</sup>
292
293setData(unifiedData: UnifiedData): void
294
295Sets drag-related data in the drag event.
296
297**Atomic service API**: This API can be used in atomic services since API version 11.
298
299**System capability**: SystemCapability.ArkUI.ArkUI.Full
300
301**Parameters**
302
303| Name     | Type                                                        | Mandatory| Description            |
304| ----------- | ------------------------------------------------------------ | ---- | ---------------- |
305| unifiedData | [UnifiedData](#unifieddata10) | Yes  | Drag-related data.|
306
307### getData<sup>10+</sup>
308
309getData(): UnifiedData
310
311Obtains drag-related data.
312
313**Atomic service API**: This API can be used in atomic services since API version 11.
314
315**System capability**: SystemCapability.ArkUI.ArkUI.Full
316
317**Return value**
318
319| Type                                                        | Description                                                        |
320| ------------------------------------------------------------ | ------------------------------------------------------------ |
321| [UnifiedData](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata) | Drag-related data. For details about the data obtaining result, see the error code description.|
322
323**Error codes**
324
325For details about the error codes, see [Drag Event Error Codes](../errorcode-drag-event.md).
326
327| ID  | Error Message|
328| --------- | ------- |
329| 190001    | Data not found.|
330| 190002    | Data error. |
331
332### getSummary<sup>10+</sup>
333
334getSummary(): Summary
335
336Obtains a summary of the dragged data, including data types and size information. When used in deferred drag scenarios, this API returns only data type information.
337
338**Atomic service API**: This API can be used in atomic services since API version 11.
339
340**System capability**: SystemCapability.ArkUI.ArkUI.Full
341
342**Return value**
343
344| Type                                                        | Description                                 |
345| ------------------------------------------------------------ | ------------------------------------- |
346| [Summary](#summary10) | Obtains the summary of drag-related data from the drag event.|
347
348### setResult<sup>10+</sup>
349
350setResult(dragResult: DragResult): void
351
352Sets the drag and drop result in the drag event.
353
354**Atomic service API**: This API can be used in atomic services since API version 11.
355
356**System capability**: SystemCapability.ArkUI.ArkUI.Full
357
358**Parameters**
359
360| Name    | Type                               | Mandatory| Description      |
361| ---------- | ----------------------------------- | ---- | ---------- |
362| dragResult | [DragResult](#dragresult10) | Yes  | Drag result.|
363
364### getResult<sup>10+</sup>
365
366getResult(): DragResult
367
368Obtains the drag result.
369
370**Atomic service API**: This API can be used in atomic services since API version 11.
371
372**System capability**: SystemCapability.ArkUI.ArkUI.Full
373
374**Return value**
375
376| Type                               | Description                         |
377| ----------------------------------- | ----------------------------- |
378| [DragResult](#dragresult10) | Drag result.|
379
380### getPreviewRect<sup>10+</sup>
381
382getPreviewRect(): Rectangle
383
384Obtains the position of the drag preview image relative to the current window, along with its size information.
385
386**Atomic service API**: This API can be used in atomic services since API version 11.
387
388**System capability**: SystemCapability.ArkUI.ArkUI.Full
389
390**Return value**
391
392| Type                                                        | Description                                                        |
393| ------------------------------------------------------------ | ------------------------------------------------------------ |
394| [Rectangle](ts-universal-attributes-touch-target.md#rectangle) | Position of the drag preview image relative to the current window, along with its size information, in vp units. **x** and **y** represent the coordinates of the upper left corner of the preview image, while **width** and **height** represent the size of the preview image.|
395
396### getVelocityX<sup>10+</sup>
397
398getVelocityX(): number
399
400Obtains the dragging velocity along the x-axis.
401
402**Atomic service API**: This API can be used in atomic services since API version 11.
403
404**System capability**: SystemCapability.ArkUI.ArkUI.Full
405
406**Return value**
407
408| Type  | Description                                                        |
409| ------ | ------------------------------------------------------------ |
410| number | Dragging velocity along the x-axis. The origin of the coordinate axis is the upper left corner of the screen. The unit is vp. The velocity is positive if the movement is from left to right, and it is negative if the movement is from right to left.|
411
412### getVelocityY<sup>10+</sup>
413
414getVelocityY(): number
415
416Obtains the dragging velocity along the y-axis.
417
418**Atomic service API**: This API can be used in atomic services since API version 11.
419
420**System capability**: SystemCapability.ArkUI.ArkUI.Full
421
422**Return value**
423
424| Type  | Description                                                        |
425| ------ | ------------------------------------------------------------ |
426| number | Dragging velocity along the y-axis. The origin of the coordinate axis is the upper left corner of the screen. The unit is vp. The velocity is positive if the movement is from top to bottom, and it is negative if the movement is from bottom to top.|
427
428### getVelocity<sup>10+</sup>
429
430getVelocity(): number
431
432Obtains the dragging velocity along the main axis.
433
434**Atomic service API**: This API can be used in atomic services since API version 11.
435
436**System capability**: SystemCapability.ArkUI.ArkUI.Full
437
438**Return value**
439
440| Type  | Description                                                        |
441| ------ | ------------------------------------------------------------ |
442| number | Dragging velocity along the main axis. The value is the arithmetic square root of the sum of squares of the velocity along the x- and y-axis.|
443
444### getWindowX<sup>10+</sup>
445
446getWindowX(): number
447
448Obtains the x-coordinate of the drag position relative to the upper left corner of the window.
449
450**Atomic service API**: This API can be used in atomic services since API version 11.
451
452**System capability**: SystemCapability.ArkUI.ArkUI.Full
453
454**Return value**
455
456| Type  | Description                                           |
457| ------ | ----------------------------------------------- |
458| number | X-coordinate of the drag position relative to the upper left corner of the window, in vp.|
459
460### getWindowY<sup>10+</sup>
461
462getWindowY(): number
463
464Obtains the y-coordinate of the drag position relative to the upper left corner of the window.
465
466**Atomic service API**: This API can be used in atomic services since API version 11.
467
468**System capability**: SystemCapability.ArkUI.ArkUI.Full
469
470**Return value**
471
472| Type  | Description                                           |
473| ------ | ----------------------------------------------- |
474| number | Y-coordinate of the drag position relative to the upper left corner of the window, in vp.|
475
476### getDisplayX<sup>10+</sup>
477
478getDisplayX(): number
479
480Obtains the x-coordinate of the drag position relative to the upper left corner of the display.
481
482**Atomic service API**: This API can be used in atomic services since API version 11.
483
484**System capability**: SystemCapability.ArkUI.ArkUI.Full
485
486**Return value**
487
488| Type  | Description                                           |
489| ------ | ----------------------------------------------- |
490| number | X-coordinate of the drag position relative to the upper left corner of the display, in vp.|
491
492### getDisplayY<sup>10+</sup>
493
494getDisplayY(): number
495
496Obtains the y-coordinate of the drag position relative to the upper left corner of the display.
497
498**Atomic service API**: This API can be used in atomic services since API version 11.
499
500**System capability**: SystemCapability.ArkUI.ArkUI.Full
501
502**Return value**
503
504| Type  | Description                                           |
505| ------ | ----------------------------------------------- |
506| number | Y-coordinate of the drag position relative to the upper left corner of the display, in vp.|
507
508### getModifierKeyState<sup>12+</sup>
509
510getModifierKeyState?(keys: Array<string\>): boolean
511
512Obtains the pressed status of modifier keys.
513
514**Atomic service API**: This API can be used in atomic services since API version 13.
515
516**System capability**: SystemCapability.ArkUI.ArkUI.Full
517
518| Name| Type               | Mandatory| Description                                                        |
519| ------ | ------------------- | ---- | ------------------------------------------------------------ |
520| keys   | Array&lt;string&gt; | Yes  | Obtains the pressed status of modifier keys. For details about the error message, see the following error codes. The following modifier keys are supported: 'Ctrl'\| 'Alt' \| 'Shift'.<br>**NOTE**<br>This API is not supported in stylus scenarios.|
521
522**Error codes**
523
524For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md).
525
526| ID  | Error Message|
527| --------- | ------- |
528| 401       | Parameter error. Possible causes: 1. Incorrect parameter types. 2. Parameter verification failed. |
529
530**Return value**
531
532| Type   | Description                                                 |
533| ------- | ----------------------------------------------------- |
534| boolean | Whether the specified modifier keys are pressed. Returns **true** if the specified modifier keys are pressed; returns **false** otherwise.|
535
536### startDataLoading<sup>15+</sup>
537
538startDataLoading(options: DataSyncOptions): string
539
540Asynchronously obtains drag data and notifies you of the current data synchronization progress. This API is only supported during the **onDrop** phase.
541
542**Atomic service API**: This API can be used in atomic services since API version 15.
543
544**System capability**: SystemCapability.ArkUI.ArkUI.Full
545
546**Parameters**
547
548| Name | Type                                 | Mandatory| Description                                                        |
549| ------- | ------------------------------------- | ---- | ------------------------------------------------------------ |
550| options | [DataSyncOptions](#datasyncoptions15) | Yes  | Drag data configuration. Data transfer can be canceled using the [cancelDataLoading](../arkts-apis-uicontext-dragcontroller.md#canceldataloading15) API.|
551
552**Error codes**
553
554For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md) and [Drag Event Error Codes](../errorcode-drag-event.md).
555
556| ID  | Error Message|
557| --------- | ------- |
558| 401       | Parameter error. |
559| 190003    | Operation not allowed for current phase. |
560
561**Return value**
562
563| Type  | Description                              |
564| ------ | ---------------------------------- |
565| string | Identifier for the drag data. It is used to distinguish between different drag operations.|
566
567### getDisplayId<sup>20+</sup>
568
569getDisplayId(): number
570
571Obtains the ID of the screen where this drag event occurs. This API is not supported when **eventType** is **NODE_ON_DRAG_END**.
572
573**Atomic service API**: This API can be used in atomic services since API version 20.
574
575**System capability**: SystemCapability.ArkUI.ArkUI.Full
576
577**Return value**
578
579| Type  | Description                            |
580| ------ | -------------------------------- |
581| number | ID of the screen where the current drag event occurs.|
582
583### getDragSource<sup>20+</sup>
584
585getDragSource(): string
586
587Obtains the package name of the drag source application.
588
589**Atomic service API**: This API can be used in atomic services since API version 20.
590
591**System capability**: SystemCapability.ArkUI.ArkUI.Full
592
593**Return value**
594
595| Type  | Description          |
596| ------ | -------------- |
597| string | Package name of the drag source application.|
598
599### isRemote<sup>20+</sup>
600
601isRemote(): boolean
602
603Checks whether the drag operation is cross-device.
604
605**Atomic service API**: This API can be used in atomic services since API version 20.
606
607**System capability**: SystemCapability.ArkUI.ArkUI.Full
608
609**Return value**
610
611| Type   | Description                                                        |
612| ------- | ------------------------------------------------------------ |
613| boolean | Whether the drag operation is cross-device. Returns **true** for cross-device drag operations; returns **false** otherwise.|
614
615### setDataLoadParams<sup>20+</sup>
616
617setDataLoadParams(dataLoadParams: DataLoadParams): void
618
619Sets the parameters for deferred data loading from the drag source. This API provides data loading parameters to the system instead of directly providing complete data objects. When the user drops data on the target application, the system will use these parameters to request the actual data from the drag source. If this API is used together with [setData](#setdata10), the last called API takes precedence.
620
621**Atomic service API**: This API can be used in atomic services since API version 20.
622
623**System capability**: SystemCapability.ArkUI.ArkUI.Full
624
625**Parameters**
626
627| Name  | Type  | Mandatory   | Description                                                        |
628| -------| -------| ------- | ------------------------------------------------------------ |
629| dataLoadParams | [DataLoadParams](#dataloadparams20) |  Yes| Data loading parameters used during a drop operation.|
630
631### getX<sup>(deprecated)</sup>
632
633getX(): number
634
635Obtains the x-coordinate of the drag position relative to the upper left corner of the window, in vp. This API is deprecated since API version 10. You are advised to use [getWindowX()](#getwindowx10) instead.
636
637**System capability**: SystemCapability.ArkUI.ArkUI.Full
638
639**Return value**
640
641| Type  | Description                                               |
642| ------ | --------------------------------------------------- |
643| number | X-coordinate of the drag position relative to the upper left corner of the window, in vp.|
644
645### getY<sup>(deprecated)</sup>
646
647getY(): number
648
649Obtains the y-coordinate of the drag position relative to the upper left corner of the window, in vp. This API is deprecated since API version 10. You are advised to use [getWindowY()](#getwindowy10) instead.
650
651**System capability**: SystemCapability.ArkUI.ArkUI.Full
652
653**Return value**
654
655| Type  | Description                                               |
656| ------ | --------------------------------------------------- |
657| number | Y-coordinate of the drag position relative to the upper left corner of the window, in vp.|
658
659### getGlobalDisplayX<sup>20+</sup>
660
661getGlobalDisplayX(): number
662
663Obtains the x-coordinate of the drag position relative to the upper left corner of the global display.
664
665**Atomic service API**: This API can be used in atomic services since API version 20.
666
667**System capability**: SystemCapability.ArkUI.ArkUI.Full
668
669**Return value**
670
671| Type  | Description                                               |
672| ------ | --------------------------------------------------- |
673| number | X-coordinate of the drag position relative to the upper left corner of the global display.<br>Unit: vp.<br>Value range: [0, +∞).|
674
675### getGlobalDisplayY<sup>20+</sup>
676
677getGlobalDisplayY(): number
678
679Obtains the y-coordinate of the drag position relative to the upper left corner of the global display.
680
681**Atomic service API**: This API can be used in atomic services since API version 20.
682
683**System capability**: SystemCapability.ArkUI.ArkUI.Full
684
685**Return value**
686
687| Type  | Description                                               |
688| ------ | --------------------------------------------------- |
689| number | Y-coordinate of the drag position relative to the upper left corner of the global display.<br>Unit: vp.<br>Value range: [0, +∞).|
690
691## DragResult<sup>10+</sup>
692
693**Atomic service API**: This API can be used in atomic services since API version 11.
694
695**System capability**: SystemCapability.ArkUI.ArkUI.Full
696
697| Name  | Value| Description|
698| ----- | -- | --------------- |
699| DRAG_SUCCESSFUL | 0 |The drag and drop operation succeeded. It can be used in **onDrop**.|
700| DRAG_FAILED | 1 |The drag and drop operation failed. It can be used in **onDrop**.|
701| DRAG_CANCELED | 2 |The drag and drop operation was canceled. It can be used in **onDrop**.|
702| DROP_ENABLED | 3 |The component allows for a drop operation. It can be used in **onDragMove**.|
703| DROP_DISABLED | 4 |The component does not allow for a drop operation. It can be used in **onDragMove**.|
704
705## DragBehavior<sup>10+</sup>
706
707Describes the drag behavior. When [DragResult](#dragresult10) is set to **DROP_ENABLED**, you can define **DragBehavior** as either **COPY** or **MOVE**. **DragBehavior** is used to indicate the intended way of handling data (either copy or move) without governing the actual data processing. This behavior is reported back to the drag source through **onDragEnd**, enabling the drag initiator to distinguish whether the operation results in a copy or a move of the data.
708
709**Atomic service API**: This API can be used in atomic services since API version 11.
710
711**System capability**: SystemCapability.ArkUI.ArkUI.Full
712
713| Name| Value| Description|
714| ----- | -- | ----------------- |
715| COPY | - |The data is handled as a copy operation.|
716| MOVE| - |The data is handled as a move operation, effectively cutting it from its original location.|
717
718## PreDragStatus<sup>12+</sup>
719
720**System capability**: SystemCapability.ArkUI.ArkUI.Full
721
722| Name| Value| Description|
723| ---- | - | ----------------- |
724| ACTION_DETECTING_STATUS | 0 | A drag gesture is being detected. (Triggered when the component is long pressed for 50 ms.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
725| READY_TO_TRIGGER_DRAG_ACTION | 1 | The component is ready to be dragged. (Triggered when the component is long pressed for 500 ms.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
726| PREVIEW_LIFT_STARTED | 2 | A lift animation is started. (Triggered when the component is long pressed for 800 ms.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
727| PREVIEW_LIFT_FINISHED | 3 | A lift animation is finished. (Triggered at the completion of the lift animation.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
728| PREVIEW_LANDING_STARTED | 4 | A drop animation is started. (Triggered when the drop animation starts.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
729| PREVIEW_LANDING_FINISHED | 5 | A drop animation is finished. (Triggered when the drop animation ends.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
730| ACTION_CANCELED_BEFORE_DRAG | 6 | A drop animation is terminated. (Triggered when the finger is lifted off the screen after the component enters the **READY_TO_TRIGGER_DRAG_ACTION** state.)<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
731| PREPARING_FOR_DRAG_DETECTION<sup>18+</sup>  | 7 | The component is ready to be dragged. (Triggered when the component is long pressed for 350 ms.)<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
732
733## UnifiedData<sup>10+</sup>
734
735type UnifiedData = UnifiedData
736
737Defines drag-related data.
738
739**Atomic service API**: This API can be used in atomic services since API version 11.
740
741**System capability**: SystemCapability.ArkUI.ArkUI.Full
742
743| Type| Description|
744| ----- | ----------------- |
745| [UnifiedData](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata) |  Drag-related data.|
746
747## Summary<sup>10+</sup>
748
749type Summary = Summary
750
751Provides a summary of drag-related data.
752
753**Atomic service API**: This API can be used in atomic services since API version 11.
754
755**System capability**: SystemCapability.ArkUI.ArkUI.Full
756
757| Type| Description|
758| ----- | ----------------- |
759| [Summary](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#summary) | Summary of drag-related data.|
760
761## DataLoadParams<sup>20+</sup>
762
763type DataLoadParams = DataLoadParams
764
765Defines the data loading parameters used during a drop operation.
766
767**Atomic service API**: This API can be used in atomic services since API version 20.
768
769**System capability**: SystemCapability.ArkUI.ArkUI.Full
770
771| Type| Description|
772| ----- | ----------------- |
773| [DataLoadParams](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#dataloadparams20) | Data loading parameters used during a drop operation.|
774
775## executeDropAnimation<sup>18+</sup>
776
777executeDropAnimation(customDragAnimation: Callback\<void\>): void
778
779Implements a custom drop animation execution function, which is only effective when **useCustomDropAnimation** is set to **true**.
780
781**Atomic service API**: This API can be used in atomic services since API version 18.
782
783**System capability**: SystemCapability.ArkUI.ArkUI.Full
784
785| Name   | Type | Mandatory| Description     |
786| ------ | ------ | --- | --------- |
787| customDropAnimation | Callback\<void\>  | Yes|Custom drop animation.<br> **NOTE**<br>1. This API is only effective when used in the **onDrop** callback.<br> 2. For the API to take effect, set **useCustomDropAnimation** to **true** before using this API.<br> 3. Do not implement logic unrelated to the animation in the animation callback to avoid affecting performance.|
788
789## DataSyncOptions<sup>15+</sup>
790
791type DataSyncOptions = GetDataParams
792
793Defines the input parameter object for **startDataLoading**.
794
795**Atomic service API**: This API can be used in atomic services since API version 15.
796
797**System capability**: SystemCapability.ArkUI.ArkUI.Full
798
799| Type| Description|
800| ----- | ----------------- |
801| [GetDataParams](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#getdataparams15) | Parameters for obtaining data from UDMF, including target path, file conflict options, progress indicator type, and other relevant settings.|
802
803## OnDragEventCallback<sup>15+</sup>
804
805type OnDragEventCallback = (event: DragEvent, extraParams?: string) => void
806
807Defines a callback for drag events.
808
809**Atomic service API**: This API can be used in atomic services since API version 15.
810
811**System capability**: SystemCapability.ArkUI.ArkUI.Full
812
813| Name| Type|Mandatory|Description|
814| ----- | ----------------- | ----- | ----- |
815| event | [DragEvent](#dragevent7)| Yes|  Information about the drag event, including the coordinates of the item that is being dragged.|
816| extraParams| string |No| Additional information about the drag event. The value needs to be parsed into the JSON format. For details, see [extraParams](#extraparams).|
817
818## DropOptions<sup>15+</sup>
819
820Provides parameters for the drop process.
821
822**Atomic service API**: This API can be used in atomic services since API version 15.
823
824**System capability**: SystemCapability.ArkUI.ArkUI.Full
825
826| Name    | Type | Read-Only| Optional| Description          |
827| ------ | ------ | ---------------- | ------ | ------ |
828| disableDataPrefetch | bool  | No | No | Whether to disable data prefetching for the drop and drop operation. The value **true** means to disable data prefetching for the drop and drop operation, and **false** means the opposite. Default value: **false**.<br>**NOTE**<br> Set this parameter to **true** when using **startDataLoading** to enable data prefetching.|
829
830## SpringLoadingContext<sup>20+</sup>
831
832type SpringLoadingContext = SpringLoadingContext
833
834Defines the callback context information, which is passed to the application in the hover detection callback to allow the application to access the drag status.
835
836**Atomic service API**: This API can be used in atomic services since API version 20.
837
838**System capability**: SystemCapability.ArkUI.ArkUI.Full
839
840| Type| Description|
841| ----- | ----------------- |
842| [SpringLoadingContext](../js-apis-arkui-dragController.md#springloadingcontext20) | Callback context information, which is passed to the application in the hover detection callback to allow the application to access the drag status.|
843
844## Example
845
846### Example 1: Setting Draggable and Droppable Areas
847
848This example demonstrates the setup for draggable and droppable areas for certain components, such as **Image** and **Text**.
849
850```ts
851// xxx.ets
852import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
853import { promptAction } from '@kit.ArkUI';
854import { BusinessError } from '@kit.BasicServicesKit';
855
856@Entry
857@Component
858struct Index {
859  @State targetImage: string = '';
860  @State targetText: string = 'Drag Text';
861  @State imageWidth: number = 100;
862  @State imageHeight: number = 100;
863  @State imgState: Visibility = Visibility.Visible;
864  @State abstractContent: string = "abstract";
865  @State textContent: string = "";
866  @State backGroundColor: Color = Color.Transparent;
867
868  @Builder
869  pixelMapBuilder() {
870    Column() {
871      Image($r('app.media.icon'))
872        .width(120)
873        .height(120)
874        .backgroundColor(Color.Yellow)
875    }
876  }
877
878  getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) {
879    try {
880      let data: UnifiedData = event.getData();
881      if (!data) {
882        return false;
883      }
884      let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
885      if (!records || records.length <= 0) {
886        return false;
887      }
888      callback(event);
889      return true;
890    } catch (e) {
891      console.error("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message);
892      return false;
893    }
894  }
895
896  getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) {
897    if (this.getDataFromUdmfRetry(event, callback)) {
898      return;
899    }
900    setTimeout(() => {
901      this.getDataFromUdmfRetry(event, callback);
902    }, 1500);
903  }
904
905  private PreDragChange(preDragStatus: PreDragStatus): void {
906    if (preDragStatus == PreDragStatus.READY_TO_TRIGGER_DRAG_ACTION) {
907      this.backGroundColor = Color.Red;
908    } else if (preDragStatus == PreDragStatus.ACTION_CANCELED_BEFORE_DRAG
909      || preDragStatus == PreDragStatus.PREVIEW_LANDING_FINISHED) {
910      this.backGroundColor = Color.Blue;
911    }
912  }
913
914  build() {
915    Row() {
916      Column() {
917        Text('start Drag')
918          .fontSize(18)
919          .width('100%')
920          .height(40)
921          .margin(10)
922          .backgroundColor('#008888')
923        Image($r('app.media.icon'))
924          .width(100)
925          .height(100)
926          .draggable(true)
927          .margin({ left: 15 })
928          .visibility(this.imgState)
929          .onDragEnd((event) => {
930            // The result value obtained from onDragEnd is set in onDrop of the drop target.
931            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
932              this.getUIContext().getPromptAction().showToast({ duration: 100, message: 'Drag Success' });
933            } else if (event.getResult() === DragResult.DRAG_FAILED) {
934              this.getUIContext().getPromptAction().showToast({ duration: 100, message: 'Drag failed' });
935            }
936          })
937        Text('test drag event')
938          .width('100%')
939          .height(100)
940          .draggable(true)
941          .margin({ left: 15 })
942          .copyOption(CopyOptions.InApp)
943        TextArea({ placeholder: 'please input words' })
944          .copyOption(CopyOptions.InApp)
945          .width('100%')
946          .height(50)
947          .draggable(true)
948        Search({ placeholder: 'please input you word' })
949          .searchButton('Search')
950          .width('100%')
951          .height(80)
952          .textFont({ size: 20 })
953
954        Column() {
955          Text('this is abstract')
956            .fontSize(20)
957            .width('100%')
958        }.margin({ left: 40, top: 20 })
959        .width('100%')
960        .height(100)
961        .onDragStart((event) => {
962          this.backGroundColor = Color.Transparent;
963          let data: unifiedDataChannel.PlainText = new unifiedDataChannel.PlainText();
964          data.abstract = 'this is abstract';
965          data.textContent = 'this is content this is content';
966          (event as DragEvent).setData(new unifiedDataChannel.UnifiedData(data));
967        })
968        .onPreDrag((status: PreDragStatus) => {
969          this.PreDragChange(status);
970        })
971        .backgroundColor(this.backGroundColor)
972      }.width('45%')
973      .height('100%')
974
975      Column() {
976        Text('Drag Target Area')
977          .fontSize(20)
978          .width('100%')
979          .height(40)
980          .margin(10)
981          .backgroundColor('#008888')
982        Image(this.targetImage)
983          .width(this.imageWidth)
984          .height(this.imageHeight)
985          .draggable(true)
986          .margin({ left: 15 })
987          .border({ color: Color.Black, width: 1 })
988          .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
989          .onDrop((dragEvent?: DragEvent) => {
990            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
991              let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
992              let rect: Rectangle = event.getPreviewRect();
993              this.imageWidth = Number(rect.width);
994              this.imageHeight = Number(rect.height);
995              this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri;
996              event.useCustomDropAnimation = false;
997              this.imgState = Visibility.None;
998              // If result is explicitly set to successful, the value is passed in to onDragEnd of the drag source.
999              event.setResult(DragResult.DRAG_SUCCESSFUL);
1000            })
1001          })
1002
1003        Text(this.targetText)
1004          .width('100%')
1005          .height(100)
1006          .border({ color: Color.Black, width: 1 })
1007          .margin(15)
1008          .allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT])
1009          .onDrop((dragEvent?: DragEvent) => {
1010            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
1011              let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
1012              let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
1013              this.targetText = plainText.textContent;
1014            })
1015          })
1016
1017        Column() {
1018          Text(this.abstractContent).fontSize(20).width('100%')
1019          Text(this.textContent).fontSize(15).width('100%')
1020        }
1021        .width('100%')
1022        .height(100)
1023        .margin(20)
1024        .border({ color: Color.Black, width: 1 })
1025        .allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT])
1026        .onDrop((dragEvent?: DragEvent) => {
1027          this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
1028            let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
1029            let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
1030            this.abstractContent = plainText.abstract as string;
1031            this.textContent = plainText.textContent;
1032          })
1033        })
1034      }.width('45%')
1035      .height('100%')
1036      .margin({ left: '5%' })
1037    }
1038    .height('100%')
1039  }
1040}
1041```
1042![events-drag-drop](figures/events-drag-drop.png)
1043
1044### Example 2: Implementing a Custom Drop Animation
1045
1046This example demonstrates how to implement a custom drop animation using the **executeDropAnimation** API.
1047```ts
1048import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
1049
1050@Entry
1051@Component
1052struct DropAnimationExample {
1053  @State targetImage: string = '';
1054  @State targetText: string = 'Drag Text';
1055  @State hyperLinkText: string = 'HyperLink';
1056  @State hyperLinkContent: string = 'HyperLink';
1057  @State imageWidth: number = 100;
1058  @State imageHeight: number = 100;
1059  @State imgState: Visibility = Visibility.Visible;
1060  @State videoSrc: string = 'resource://RAWFILE/02.mp4';
1061  @State abstractContent: string = "abstract";
1062  @State textContent: string = "";
1063
1064  customDropAnimation =
1065    () => {
1066      this.getUIContext().animateTo({ duration: 1000, curve: Curve.EaseOut, playMode: PlayMode.Normal }, () => {
1067        this.imageWidth = 200;
1068        this.imageHeight = 200;
1069        this.imgState = Visibility.None;
1070      })
1071    }
1072
1073  build() {
1074    Row() {
1075      Column() {
1076        Image($r('app.media.app_icon'))
1077          .width(100)
1078          .height(100)
1079          .draggable(true)
1080          .margin({ left: 15 ,top: 40})
1081          .visibility(this.imgState)
1082          .onDragStart((event) => {
1083          })
1084          .onDragEnd((event) => {
1085            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
1086              console.info('Drag Success');
1087            } else if (event.getResult() === DragResult.DRAG_FAILED) {
1088              console.error('Drag failed');
1089            }
1090          })
1091      }.width('45%')
1092      .height('100%')
1093      Column() {
1094        Text('Drag Target Area')
1095          .fontSize(20)
1096          .width(180)
1097          .height(40)
1098          .textAlign(TextAlign.Center)
1099          .margin(10)
1100          .backgroundColor('rgb(240,250,255)')
1101        Column() {
1102          Image(this.targetImage)
1103            .width(this.imageWidth)
1104            .height(this.imageHeight)
1105        }
1106        .draggable(true)
1107        .margin({ left: 15 })
1108        .border({ color: Color.Black, width: 1 })
1109        .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
1110        .onDrop((dragEvent: DragEvent) => {
1111          let records: Array<unifiedDataChannel.UnifiedRecord> = dragEvent.getData().getRecords();
1112          let rect: Rectangle = dragEvent.getPreviewRect();
1113          this.imageWidth = Number(rect.width);
1114          this.imageHeight = Number(rect.height);
1115          this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri;
1116          dragEvent.useCustomDropAnimation = true;
1117          dragEvent.executeDropAnimation(this.customDropAnimation)
1118        })
1119        .width(this.imageWidth)
1120        .height(this.imageHeight)
1121      }.width('45%')
1122      .height('100%')
1123      .margin({ left: '5%' })
1124    }
1125    .height('100%')
1126  }
1127}
1128```
1129![executeDropAnimation](figures/executeDropAnimation.gif)
1130
1131### Example 3: Obtaining Data Asynchronously Through Drag-and-Drop
1132
1133This example demonstrates how to asynchronously obtain data using **startDataLoading** during a drag-and-drop operation.
1134
1135```ts
1136import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
1137import { fileUri, fileIo as fs } from '@kit.CoreFileKit';
1138import { common } from '@kit.AbilityKit';
1139
1140@Entry
1141@Component
1142struct ImageExample {
1143  @State uri: string = "";
1144  @State blockArr: string[] = [];
1145  uiContext = this.getUIContext();
1146  udKey: string = '';
1147
1148  build() {
1149    Column() {
1150      Text('Image drag and drop')
1151        .fontSize('30dp')
1152      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceAround }) {
1153        Image($r('app.media.startIcon'))
1154          .width(100)
1155          .height(100)
1156          .border({ width: 1 })
1157          .draggable(true)
1158          .onDragStart((event:DragEvent) => {
1159            const context: Context|undefined = this.uiContext.getHostContext();
1160            if(context) {
1161              let data = context.resourceManager.getMediaContentSync($r('app.media.startIcon').id, 120);
1162              const arrayBuffer: ArrayBuffer = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset);
1163              let filePath = context.filesDir + '/test.png';
1164              let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
1165              fs.writeSync(file.fd, arrayBuffer);
1166              // Obtain the image URI.
1167              let uri = fileUri.getUriFromPath(filePath);
1168              let image: unifiedDataChannel.Image = new unifiedDataChannel.Image();
1169              image.imageUri = uri;
1170              let dragData: unifiedDataChannel.UnifiedData = new unifiedDataChannel.UnifiedData(image);
1171              (event as DragEvent).setData(dragData);
1172            }
1173          })
1174      }
1175      .margin({ bottom: 20 })
1176      Row() {
1177        Column(){
1178          Text('Valid drop target')
1179            .fontSize('15dp')
1180            .height('10%')
1181          List(){
1182            ForEach(this.blockArr, (item:string, index) => {
1183              ListItem() {
1184                Image(item)
1185                  .width(100)
1186                  .height(100)
1187                  .border({width: 1})
1188              }
1189              .margin({ left: 30 , top : 30})
1190            }, (item:string) => item)
1191          }
1192          .border({width: 1})
1193          .height('90%')
1194          .width('100%')
1195          .onDrop((event?: DragEvent, extraParams?: string) => {
1196            console.info("enter onDrop")
1197            let context = this.uiContext.getHostContext() as common.UIAbilityContext;
1198            let pathDir: string = context.distributedFilesDir;
1199            let destUri = fileUri.getUriFromPath(pathDir);
1200            let progressListener: unifiedDataChannel.DataProgressListener = (progress: unifiedDataChannel.ProgressInfo, dragData: UnifiedData|null) => {
1201              if(dragData != null) {
1202                let arr:Array<unifiedDataChannel.UnifiedRecord> = dragData.getRecords();
1203                if(arr.length > 0) {
1204                  if (arr[0].getType() === uniformTypeDescriptor.UniformDataType.IMAGE) {
1205                    let image = arr[0] as unifiedDataChannel.Image;
1206                    this.uri = image.imageUri;
1207                    this.blockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri);
1208                  }
1209                } else {
1210                  console.info('dragData arr is null');
1211                }
1212              } else {
1213                console.info('dragData is undefined');
1214              }
1215              console.info(`percentage: ${progress.progress}`);
1216            };
1217            let options: DataSyncOptions = {
1218              destUri: destUri,
1219              fileConflictOptions: unifiedDataChannel.FileConflictOptions.OVERWRITE,
1220              progressIndicator: unifiedDataChannel.ProgressIndicator.DEFAULT,
1221              dataProgressListener: progressListener,
1222            }
1223            try {
1224              this.udKey = (event as DragEvent).startDataLoading(options);
1225              console.info('udKey: ', this.udKey);
1226            } catch(e) {
1227              console.error(`startDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
1228            }
1229          }, {disableDataPrefetch: true})
1230        }
1231        .height("50%")
1232        .width("90%")
1233        .border({ width: 1 })
1234      }
1235      Button('Cancel data transfer')
1236        .onClick(() => {
1237          try {
1238            this.getUIContext().getDragController().cancelDataLoading(this.udKey);
1239          } catch (e) {
1240            console.error(`cancelDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
1241          }
1242        })
1243        .margin({top: 10})
1244    }.width('100%')
1245  }
1246}
1247```
1248### Example 4: Obtaining the Screen ID for the Drag Event
1249
1250This example shows how to obtain the drag event through the **onDrag*XXX*** API (note: **onDragEnd** is not supported for this), and call the **getDisplayId** API within the drag event to obtain the screen ID.
1251
1252```ts
1253import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
1254import { promptAction } from '@kit.ArkUI';
1255import { BusinessError } from '@kit.BasicServicesKit';
1256
1257@Entry
1258@Component
1259struct Index {
1260  @State targetImage: string = '';
1261  @State imageWidth: number = 100;
1262  @State imageHeight: number = 100;
1263  @State imgState: Visibility = Visibility.Visible;
1264  @State backGroundColor: Color = Color.Transparent;
1265  @State startDisplayId: number = -1;
1266  @State enterDisplayId: number = -1;
1267  @State moveDisplayId: number = -1;
1268  @State leaveDisplayId: number = -1;
1269  @State dropDisplayId: number = -1;
1270
1271  @Builder
1272  pixelMapBuilder() {
1273    Column() {
1274      Image($r('app.media.app_icon'))
1275        .width(120)
1276        .height(120)
1277        .backgroundColor(Color.Yellow)
1278    }
1279  }
1280
1281  getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) {
1282    try {
1283      let data: UnifiedData = event.getData();
1284      if (!data) {
1285        return false;
1286      }
1287      let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
1288      if (!records || records.length <= 0) {
1289        return false;
1290      }
1291      callback(event);
1292      return true;
1293    } catch (e) {
1294      console.error("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message);
1295      return false;
1296    }
1297  }
1298
1299  getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) {
1300    if (this.getDataFromUdmfRetry(event, callback)) {
1301      return;
1302    }
1303    setTimeout(() => {
1304      this.getDataFromUdmfRetry(event, callback);
1305    }, 1500);
1306  }
1307
1308  private PreDragChange(preDragStatus: PreDragStatus): void {
1309    if (preDragStatus == PreDragStatus.READY_TO_TRIGGER_DRAG_ACTION) {
1310      this.backGroundColor = Color.Red;
1311    } else if (preDragStatus == PreDragStatus.ACTION_CANCELED_BEFORE_DRAG
1312      || preDragStatus == PreDragStatus.PREVIEW_LANDING_FINISHED) {
1313      this.backGroundColor = Color.Blue;
1314    }
1315  }
1316
1317  build() {
1318    Row() {
1319      Column() {
1320        Text('start Drag')
1321          .fontSize(18)
1322          .width('100%')
1323          .height(40)
1324          .margin(10)
1325          .backgroundColor('#008888')
1326        Image($r('app.media.startIcon'))
1327          .width(100)
1328          .height(100)
1329          .draggable(true)
1330          .margin({ left: 15 })
1331          .visibility(this.imgState)
1332          .onDragStart((event) => {
1333            let id = event.getDisplayId();
1334            this.startDisplayId = id;
1335          })
1336
1337          .onDragEnd((event) => {
1338            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
1339              this.getUIContext().getPromptAction().showToast({ duration: 100, message: 'Drag Success' });
1340            } else if (event.getResult() === DragResult.DRAG_FAILED) {
1341              this.getUIContext().getPromptAction().showToast({ duration: 100, message: 'Drag failed' });
1342            }
1343          })
1344
1345        Text('displayID in onDragStart: ' + this.startDisplayId.toString())
1346          .width('100%')
1347          .height(50)
1348          .draggable(true)
1349          .margin({ left: 15 })
1350        Text('displayID in onDragEnter: ' + this.enterDisplayId.toString())
1351          .width('100%')
1352          .height(50)
1353          .draggable(true)
1354          .margin({ left: 15 })
1355        Text('displayID in onDragMove: ' + this.moveDisplayId.toString())
1356          .width('100%')
1357          .height(50)
1358          .draggable(true)
1359          .margin({ left: 15 })
1360        Text('displayID in onDragLeave: ' + this.leaveDisplayId.toString())
1361          .width('100%')
1362          .height(50)
1363          .draggable(true)
1364          .margin({ left: 15 })
1365        Text('displayID in onDrop: ' + this.dropDisplayId.toString())
1366          .width('100%')
1367          .height(50)
1368          .draggable(true)
1369          .margin({ left: 15 })
1370          .onPreDrag((status: PreDragStatus) => {
1371            this.PreDragChange(status);
1372          })
1373      }.width('45%')
1374      .height('100%')
1375
1376      Column() {
1377        Text('Drag Target Area')
1378          .fontSize(20)
1379          .width('100%')
1380          .height(40)
1381          .margin(10)
1382          .backgroundColor('#008888')
1383        Image(this.targetImage)
1384          .width(this.imageWidth)
1385          .height(this.imageHeight)
1386          .draggable(true)
1387          .margin({ left: 15 })
1388          .border({ color: Color.Black, width: 1 })
1389          .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
1390          .onDragEnter((event) => {
1391            let id = event.getDisplayId();
1392            this.enterDisplayId = id;
1393          })
1394          .onDragMove((event) => {
1395            let id = event.getDisplayId();
1396            this.moveDisplayId = id;
1397          })
1398          .onDragLeave((event) => {
1399            let id = event.getDisplayId();
1400            this.leaveDisplayId = id;
1401          })
1402          .onDrop((dragEvent: DragEvent) => {
1403            let id = dragEvent.getDisplayId();
1404            this.dropDisplayId = id;
1405            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
1406              let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
1407              let rect: Rectangle = event.getPreviewRect();
1408              this.imageWidth = Number(rect.width);
1409              this.imageHeight = Number(rect.height);
1410              this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri;
1411              event.useCustomDropAnimation = false;
1412              this.imgState = Visibility.None;
1413              event.setResult(DragResult.DRAG_SUCCESSFUL);
1414            })
1415          })
1416      }.width('45%')
1417      .height('100%')
1418      .margin({ left: '5%' })
1419    }
1420    .height('100%')
1421  }
1422}
1423```
1424![DragEvent_getDisplayId](figures/DragEvent_getDisplayId.png)
1425
1426### Example 5: Obtaining the Package Name and Cross-Device Status
1427
1428This example shows how to obtain the drag event through the  **onDrag*XXX*** API, call the **getDragSource** API within the drag event to obtain the package name, and call the **isRemote** API to check whether the drag operation is cross-device.
1429
1430```ts
1431@Entry
1432@Component
1433struct Index {
1434  @State targetImage: string = '';
1435  @State startDragSource: string = '';
1436  @State startIsRemote: boolean = true;
1437  @State enterDragSource: string = '';
1438  @State enterIsRemote: boolean = true;
1439
1440  build() {
1441    Column() {
1442      Row() {
1443        Column() {
1444          Text('start Drag Area')
1445            .fontSize(18)
1446            .width('100%')
1447            .height(40)
1448            .margin(10)
1449            .backgroundColor('#008888')
1450          Image($r('app.media.startIcon'))
1451            .onDragStart((event) => {
1452              this.startDragSource = (event as DragEvent).getDragSource();
1453              this.startIsRemote = (event as DragEvent).isRemote();
1454            })
1455            .width(100)
1456            .height(100)
1457            .draggable(true)
1458            .margin({ left: 15 })
1459        }
1460        .border({ color: Color.Black, width: 1 })
1461        .width('45%')
1462        .height('50%')
1463
1464        Column() {
1465          Text('Drag Target Area')
1466            .fontSize(20)
1467            .width('100%')
1468            .height(40)
1469            .margin(10)
1470            .backgroundColor('#008888')
1471          Image(this.targetImage)
1472            .width(100)
1473            .height(100)
1474            .draggable(true)
1475            .margin({ left: 15 })
1476            .border({ color: Color.Black, width: 1 })
1477            .onDragEnter((event) => {
1478              this.enterDragSource = (event as DragEvent).getDragSource();
1479              this.enterIsRemote = (event as DragEvent).isRemote();
1480            })
1481            .onDrop(()=>{})
1482        }
1483        .border({ color: Color.Black, width: 1 })
1484        .width('45%')
1485        .height('50%')
1486        .margin({ left: '5%' })
1487      }
1488      .height('70%')
1489
1490      Text('onDragStart dragSource: ' + this.startDragSource.toString() + '\n' + 'onDragStart isRemote: ' +
1491      this.startIsRemote.toString())
1492        .width('100%')
1493        .height(50)
1494        .margin({ left: 15 })
1495      Text('onDragEnter dragSource: ' + this.enterDragSource.toString() + '\n' + 'onDragEnter isRemote: ' +
1496      this.enterIsRemote.toString())
1497        .width('100%')
1498        .height(50)
1499        .margin({ left: 15 })
1500    }
1501  }
1502}
1503```
1504![dragSourceAndIsRemote](figures/dragSourceAndIsRemote.png)
1505
1506### Example 6: Implementing Hover Detection Support
1507
1508This example demonstrates how to register a callback through **onDragSpringLoading** and call **SpringLoadingContext** to obtain the context (current state and notification sequence).
1509
1510```ts
1511// xxx.ets
1512@Entry
1513@Component
1514struct Index {
1515  @State targetText: string = 'Drag Text';
1516  @State state: number = 0;
1517  @State currentNotifySequence: number = 0;
1518  @State config: DragSpringLoadingConfiguration = {
1519    stillTimeLimit: 200,
1520    updateInterval: 300,
1521    updateNotifyCount: 4,
1522    updateToFinishInterval: 300
1523  };
1524
1525  build() {
1526    Row() {
1527      Column() {
1528        Text('start Drag')
1529          .fontSize(18)
1530          .width('100%')
1531          .height(40)
1532          .margin(10)
1533          .backgroundColor('#008888')
1534        Image($r('app.media.startIcon'))
1535          .id("ori_image")
1536          .width(100)
1537          .height(100)
1538          .draggable(true)
1539          .margin({ left: 15 })
1540        Text('Current state: ' + this.state)
1541          .fontSize(18)
1542          .width('100%')
1543          .height(40)
1544          .margin(10)
1545        Text('Current notification sequence: ' + this.currentNotifySequence)
1546          .fontSize(18)
1547          .width('100%')
1548          .height(40)
1549          .margin(10)
1550      }
1551      .width('45%')
1552      .height('100%')
1553
1554      Column() {
1555        Text('Drag Target Area')
1556          .fontSize(20)
1557          .width('100%')
1558          .height(40)
1559          .margin(10)
1560          .backgroundColor('#008888')
1561          .id("text")
1562        Image("")
1563          .width(100)
1564          .height(100)
1565          .draggable(true)
1566          .margin({ left: 15 })
1567          .border({ color: Color.Black, width: 2 })
1568          .onDragSpringLoading((context: SpringLoadingContext) => {
1569            this.state = context.state;
1570            this.currentNotifySequence = context.currentNotifySequence;
1571          }, this.config)
1572      }
1573      .width('45%')
1574      .height('100%')
1575      .margin({ left: '5%' })
1576      .onDragSpringLoading((context: SpringLoadingContext) => {
1577        this.state = context.state;
1578        this.currentNotifySequence = context.currentNotifySequence;
1579      }, this.config)
1580      .id("column")
1581      .backgroundColor(Color.Grey)
1582    }
1583    .height('100%')
1584  }
1585}
1586```
1587
1588
1589### Example 7: Delaying Data Provision from the Drag Source
1590
1591This example shows how to call **setDataLoadParams** in **onDragStart** to delay data provision from the drag source, and use **startDataLoading** in **onDrop** to asynchronously obtain the data.
1592
1593```ts
1594import { unifiedDataChannel, uniformDataStruct, uniformTypeDescriptor } from '@kit.ArkData';
1595import { fileUri, fileIo as fs } from '@kit.CoreFileKit';
1596import { common } from '@kit.AbilityKit';
1597
1598@Entry
1599@Component
1600struct VideoExample {
1601  @State uri: string = "";
1602  @State blockArr: string[] = [];
1603  uiContext = this.getUIContext();
1604  udKey: string = '';
1605
1606  build() {
1607    Column() {
1608      Text('Video drag and drop')
1609        .fontSize('30dp')
1610      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceAround }) {
1611        Video({ src: $rawfile('test1.mp4'), controller: new VideoController() })
1612          .width(200)
1613          .height(200)
1614          .border({ width: 1 })
1615          .draggable(true)
1616          .onDragStart((event: DragEvent) => {
1617            const context: Context | undefined = this.uiContext.getHostContext();
1618            if (context) {
1619              let loadHandler: unifiedDataChannel.DataLoadHandler = (acceptableInfo) => {
1620                console.info('acceptableInfo recordCount', acceptableInfo?.recordCount);
1621                if (acceptableInfo?.types) {
1622                  console.info('acceptableInfo types', Array.from(acceptableInfo.types));
1623                } else {
1624                  console.error('acceptableInfo types is undefined');
1625                }
1626                let data = context.resourceManager.getRawFdSync('test1.mp4');
1627                let filePath = context.filesDir + '/test1.mp4';
1628                let file: fs.File = null!;
1629                try {
1630                  file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
1631                  let bufferSize = data.length as number;
1632                  let buf = new ArrayBuffer(bufferSize);
1633                  fs.readSync(data.fd, buf, { offset: data.offset, length: bufferSize });
1634                  fs.writeSync(file.fd, buf, { offset: 0, length: bufferSize });
1635                } catch (error) {
1636                  console.error(`openSync errorCode: ${error.code}, errorMessage: ${error.message}`);
1637                } finally {
1638                  fs.closeSync(file.fd);
1639                }
1640                context.resourceManager.closeRawFdSync('test1.mp4')
1641                this.uri = fileUri.getUriFromPath(filePath);
1642                let videoMp: uniformDataStruct.FileUri = {
1643                  uniformDataType: 'general.file-uri',
1644                  oriUri: this.uri,
1645                  fileType: 'general.video',
1646                }
1647                let unifiedRecord = new unifiedDataChannel.UnifiedRecord();
1648                let unifiedData = new unifiedDataChannel.UnifiedData();
1649                unifiedRecord.addEntry(uniformTypeDescriptor.UniformDataType.FILE_URI, videoMp);
1650                unifiedData.addRecord(unifiedRecord);
1651                return unifiedData;
1652              }
1653              (event as DragEvent).setDataLoadParams({
1654                loadHandler: loadHandler,
1655                dataLoadInfo: { types: new Set([uniformTypeDescriptor.UniformDataType.FILE_URI]), recordCount: 1 }
1656              });
1657            }
1658          })
1659      }
1660      .margin({ bottom: 20 })
1661
1662      Row() {
1663        Column() {
1664          Text('Valid drop target')
1665            .fontSize('15dp')
1666            .height('10%')
1667          List() {
1668            ForEach(this.blockArr, (item: string, index) => {
1669              ListItem() {
1670                Video({ src: item, controller: new VideoController() })
1671                  .width(100)
1672                  .height(100)
1673                  .border({ width: 1 })
1674              }
1675              .margin({ left: 30, top: 30 })
1676            }, (item: string) => item)
1677          }
1678          .border({ width: 1 })
1679          .height('90%')
1680          .width('100%')
1681          .onDrop((event: DragEvent, extraParams?: string) => {
1682            let context = this.uiContext.getHostContext() as common.UIAbilityContext;
1683            let pathDir: string = context.distributedFilesDir;
1684            let destUri = fileUri.getUriFromPath(pathDir);
1685            let progressListener: unifiedDataChannel.DataProgressListener =
1686              (progress: unifiedDataChannel.ProgressInfo, dragData: UnifiedData | null) => {
1687                if (dragData != null) {
1688                  let arr: Array<unifiedDataChannel.UnifiedRecord> = dragData.getRecords();
1689                  if (arr.length > 0) {
1690                    if (arr[0].getType() === uniformTypeDescriptor.UniformDataType.VIDEO) {
1691                      this.blockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri);
1692                    }
1693                  } else {
1694                    console.info('dragData arr is null');
1695                  }
1696                } else {
1697                  console.info('dragData is undefined');
1698                }
1699                console.info(`percentage: ${progress.progress}`);
1700              };
1701            let info: unifiedDataChannel.DataLoadInfo =
1702              { types: new Set([uniformTypeDescriptor.UniformDataType.VIDEO]), recordCount: 100 }
1703            let options: DataSyncOptions = {
1704              destUri: destUri,
1705              fileConflictOptions: unifiedDataChannel.FileConflictOptions.OVERWRITE,
1706              progressIndicator: unifiedDataChannel.ProgressIndicator.DEFAULT,
1707              dataProgressListener: progressListener,
1708              acceptableInfo: info,
1709            }
1710            try {
1711              this.udKey = (event as DragEvent).startDataLoading(options);
1712              console.info('udKey: ', this.udKey);
1713            } catch (e) {
1714              console.error(`startDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
1715            }
1716          }, { disableDataPrefetch: true })
1717        }
1718        .height("50%")
1719        .width("90%")
1720        .border({ width: 1 })
1721      }
1722
1723      Button('Cancel data transfer')
1724        .onClick(() => {
1725          try {
1726            this.getUIContext().getDragController().cancelDataLoading(this.udKey);
1727          } catch (e) {
1728            console.error(`cancelDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
1729          }
1730        })
1731        .margin({ top: 10 })
1732    }.width('100%')
1733  }
1734}
1735```
1736
1737