• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Drag Event
2
3A drag event is triggered when a component is dragged.
4
5>  **NOTE**
6>
7>  The APIs of this module are supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version.
8>
9> 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.
10
11The 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.
12
13- 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), <!--Del-->[FormComponent](ts-basic-components-formcomponent-sys.md), <!--DelEnd-->[Hyperlink](ts-container-hyperlink.md). You can control the default drag behavior by setting the [draggable](ts-universal-attributes-drag-drop.md#draggable) attribute.
14
15- 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**.
16
17<!--RP1--><!--RP1End-->To 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**.
18
19> **NOTE**
20>
21> When using the **Text** component, set [copyOption](ts-basic-components-text.md#copyoption9) to **CopyOptions.InApp** or **CopyOptions.LocalDevice**.
22
23## onDragStart
24
25onDragStart(event: (event: DragEvent, extraParams?: string) => CustomBuilder | DragItemInfo)
26
27Triggered 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.
28
29For components that can serve as the drag source by default, a custom **onDragStart** event, if set, is executed and:
30- If a custom drag preview is returned, it is used in place of the default drag preview.
31- If drag data is set, it is used in place of the default drag data.
32
33No 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.
34
35**Atomic service API**: This API can be used in atomic services since API version 11.
36
37**Event priority**:<br>Long press time < 500 ms: Long press event > Drag event<br>Other cases: Drag event > Long press event
38
39**System capability**: SystemCapability.ArkUI.ArkUI.Full
40
41**Parameters**
42
43| Name     | Type                           | Mandatory| Description              |
44| ----------- | ------------------------------- | ---- | ------------------ |
45| 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).|
46
47**Return value**
48
49| Type                                                        | Description                    |
50| ------------------------------------------------------------ | ------------------------ |
51| [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo) | Component information displayed during dragging.<br>**NOTE**<br>The global builder is not supported.|
52
53## onDragEnter
54
55onDragEnter(event: (event: DragEvent, extraParams?: string) => void)
56
57Triggered when a dragged item enters a valid drop target. This event takes effect only when a listener for the [onDrop](#ondrop) event is enabled.
58
59**Atomic service API**: This API can be used in atomic services since API version 11.
60
61**System capability**: SystemCapability.ArkUI.ArkUI.Full
62
63**Parameters**
64
65| Name     | Type                           | Mandatory| Description                          |
66| ----------- | ------------------------------- | ---- | ------------------------------ |
67| 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).|
68
69## onDragMove
70
71onDragMove(event: (event: DragEvent, extraParams?: string) => void)
72
73Triggered 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.
74
75**Atomic service API**: This API can be used in atomic services since API version 11.
76
77**System capability**: SystemCapability.ArkUI.ArkUI.Full
78
79**Parameters**
80
81| Name     | Type                           | Mandatory| Description                          |
82| ----------- | ------------------------------- | ---- | ------------------------------ |
83| 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).|
84
85## onDragLeave
86
87onDragLeave(event: (event: DragEvent, extraParams?: string) => void)
88
89Triggered when a dragged item leaves a valid drop target. This event takes effect only when a listener for the [onDrop](#ondrop) event is enabled.
90
91**Atomic service API**: This API can be used in atomic services since API version 11.
92
93**System capability**: SystemCapability.ArkUI.ArkUI.Full
94
95**Parameters**
96
97| Name     | Type                           | Mandatory| Description                          |
98| ----------- | ------------------------------- | ---- | ------------------------------ |
99| 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).|
100
101## onDrop
102
103onDrop(event: (event: DragEvent, extraParams?: string) => void)
104
105Triggered when a dragged item is dropped on a valid drop target. 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.
106
107**Atomic service API**: This API can be used in atomic services since API version 11.
108
109**System capability**: SystemCapability.ArkUI.ArkUI.Full
110
111**Parameters**
112
113| Name     | Type                           | Mandatory| Description                          |
114| ----------- | ------------------------------- | ---- | ------------------------------ |
115| 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).|
116
117## onDrop<sup>15+</sup>
118
119onDrop(eventCallback: OnDragEventCallback, dropOptions?: DropOptions)
120
121Triggered 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.
122
123**Atomic service API**: This API can be used in atomic services since API version 15.
124
125**System capability**: SystemCapability.ArkUI.ArkUI.Full
126
127**Parameters**
128
129| Name     | Type                           | Mandatory| Description                          |
130| ----------- | ------------------------------- | ---- | ------------------------------ |
131| eventCallback  | (event: DragEvent, 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).|
132| dropOptions  | bool   | No  | Whether to enable data prefetching for the drop and drop operation.<br>**NOTE**<br> Set this parameter to **true** when using **startDataLoading** to enable data prefetching.|
133
134## onDragEnd<sup>10+</sup>
135
136onDragEnd(event: (event: DragEvent, extraParams?: string) => void)
137
138Triggered when the dragging of the component bound to the event ends.
139
140**Atomic service API**: This API can be used in atomic services since API version 11.
141
142**System capability**: SystemCapability.ArkUI.ArkUI.Full
143
144**Parameters**
145
146| Name     | Type                           | Mandatory| Description                          |
147| ----------- | ------------------------------- | ---- | ------------------------------ |
148| 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).|
149
150## onPreDrag<sup>12+</sup>
151
152onPreDrag(event: (preDragStatus: PreDragStatus) => void)
153
154Invoked when the component enters a state prior to a drop and drop operation.
155
156**Atomic service API**: This API can be used in atomic services since API version 12.
157
158**System capability**: SystemCapability.ArkUI.ArkUI.Full
159
160**Parameters**
161
162| Name     | Type                           | Mandatory| Description                          |
163| ----------- | ------------------------------- | ---- | ------------------------------ |
164| callback    | Callback<(preDragStatus: [PreDragStatus](#predragstatus12)> ) => void     | Yes  | Callback function.|
165
166## DragItemInfo
167
168**Atomic service API**: This API can be used in atomic services since API version 11.
169
170**System capability**: SystemCapability.ArkUI.ArkUI.Full
171
172| Name     | Type                                    | Mandatory  | Description                               |
173| --------- | ---------------------------------------- | ---- | --------------------------------- |
174| pixelMap  | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7) | No   | Image to be displayed during dragging.|
175| builder   | [CustomBuilder](ts-types.md#custombuilder8) | No   | 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.|
176| extraInfo | string                                   | No   | Extra information of the dragged item.                          |
177
178## PreviewConfiguration<sup>15+</sup>
179
180Defines the preview image style during a drag operation.
181
182**Atomic service API**: This API can be used in atomic services since API version 15.
183
184**System capability**: SystemCapability.ArkUI.ArkUI.Full
185
186| Name      | Type| Read-Only| Optional| Description                                                        |
187| ---------- | ---- | ---- | ---- | ------------------------------------------------------------ |
188| onlyForLifting | boolean | No   | Yes   | Whether the custom preview image is used only for lifting.<br> **NOTE**<br>The default value is **false**. 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.|
189| delayCreating  | boolean | No   | Yes   | Whether the preview builder is loaded at the time of setting.<br>The default value is **false**.|
190
191## extraParams
192
193  Provides additional information required for dragging an item.
194
195  **extraParams** is a string converted from a JSON object. You can obtain the following attributes using the JSON object converted from **Json.parse**.
196
197| Name         | Type  | Description                                      |
198| ------------- | ------ | ---------------------------------------- |
199| 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.|
200| 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.|
201
202## DragEvent<sup>7+</sup>
203
204**System capability**: SystemCapability.ArkUI.ArkUI.Full
205
206### Properties
207
208**Atomic service API**: This API can be used in atomic services since API version 11.
209
210**System capability**: SystemCapability.ArkUI.ArkUI.Full
211
212| Name    | Type | Description            |
213| ------ | ------ | ---------------- |
214| useCustomDropAnimation<sup>10+</sup> | boolean | Whether to use the custom 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.|
215|dragBehavior<sup>10+</sup> | [DragBehavior](#dragbehavior10) | Copy or paste mode.|
216
217### Methods
218
219**System capability**: SystemCapability.ArkUI.ArkUI.Full
220
221| Name    | Return Value Type                           | Description                          |
222| ----------- | ------------------------------- | ------------------------------ |
223| setData(unifiedData: [UnifiedData](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata))<sup>10+</sup>       | void   | Sets drag-related data in the drag event.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
224| getData()<sup>10+</sup> | [UnifiedData](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata) | Obtains drag-related data from the drag event. For details about the data obtaining result, see the error code description.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
225| getSummary()<sup>10+</sup> | [Summary](../../apis-arkdata/js-apis-data-unifiedDataChannel.md#summary) | Obtains the summary of drag-related data from the drag event.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
226| setResult(dragRect: [DragResult](#dragresult10))<sup>10+</sup> | void | Sets the drag and drop result in the drag event.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
227| getResult()<sup>10+</sup> | [DragResult](#dragresult10) | Obtains the drag and drop result from the drag event.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
228| getPreviewRect()<sup>10+</sup> | [Rectangle](ts-universal-attributes-touch-target.md#rectangle) | Obtains the position of the drag preview image relative to the current window, as well as the size of the preview image, 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.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
229| getVelocityX()<sup>10+</sup> | number | Obtains the 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.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
230| getVelocityY()<sup>10+</sup> | number | Obtains the 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.|
231| getVelocity()<sup>10+</sup> | number | Obtains the 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.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
232| getWindowX()<sup>10+</sup> | number | X coordinate of the drag position relative to the upper left corner of the window, in vp.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
233| getWindowY()<sup>10+</sup> | number | Y coordinate of the drag position relative to the upper left corner of the window, in vp.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
234| getDisplayX()<sup>10+</sup> | number | X coordinate of the drag position relative to the upper left corner of the screen, in vp.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
235| getDisplayY()<sup>10+</sup> | number | Y coordinate of the drag position relative to the upper left corner of the screen, in vp.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
236| getModifierKeyState<sup>12+</sup> | (Array&lt;string&gt;) => bool | 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'\|'Fn'. This API does not work for the Fn key on an externally connected keyboard.<br>**Atomic service API**: This API can be used in atomic services since API version 13.|
237| startDataLoading(options: [DataSyncOptions](#datasyncoptions15))<sup>15+</sup> | string | Asynchronously obtains drag data and notifies you of the current data synchronization progress. This API is only supported during the **onDrop** phase. Data transfer can be canceled using the [cancelDataLoading](../js-apis-arkui-UIContext.md#canceldataloading15) API.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
238| getX()<sup>(deprecated)</sup> | number | X coordinate of the drag position relative to the upper left corner of the window, in vp.<br>This API is deprecated since API version 10. You are advised to use **getWindowX()** instead.|
239| getY()<sup>(deprecated)</sup> | number | Y coordinate of the drag position relative to the upper left corner of the window, in vp.<br>This API is deprecated since API version 10. You are advised to use **getWindowY()** instead.|
240
241
242**Error codes**
243
244For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md) and [Drag Event Error Codes](../errorcode-drag-event.md).
245
246| ID  | Error Message|
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**Atomic service API**: This API can be used in atomic services since API version 11.
256
257**System capability**: SystemCapability.ArkUI.ArkUI.Full
258
259| Name| Description|
260| ----- | ----------------- |
261| DRAG_SUCCESSFUL | The drag and drop operation succeeded. It can be used in **onDrop**.|
262| DRAG_FAILED | The drag and drop operation failed. It can be used in **onDrop**.|
263| DRAG_CANCELED | The drag and drop operation was canceled. It can be used in **onDrop**.|
264| DROP_ENABLED | The component allows for a drop operation. It can be used in **onDragMove**.|
265| DROP_DISABLED | The component does not allow for a drop operation. It can be used in **onDragMove**.|
266
267## DragBehavior<sup>10+</sup>
268
269Describes the drag behavior. When [DragResult](#dragresult10) is set to **DROP_ENABLED**, you can define **DragBehavior** as either **COPY** or **MOVE**. **DragBehavior** serves to inform you about the intended method of data handling – whether it's a copy or a move –but it does not actually dictate the real processing of the data. The behavior is reported back to the drag source through **onDragEnd**, enabling the initiator of the drag to discern whether the operation results in a copy or a move of the data.
270
271**Atomic service API**: This API can be used in atomic services since API version 11.
272
273**System capability**: SystemCapability.ArkUI.ArkUI.Full
274
275| Name| Description|
276| ----- | ----------------- |
277| COPY | The data is handled as a copy operation.|
278| MOVE| The data is handled as a move operation, effectively cutting it from its original location.|
279
280## PreDragStatus<sup>12+</sup>
281
282**Atomic service API**: This API can be used in atomic services since API version 12.
283
284**System capability**: SystemCapability.ArkUI.ArkUI.Full
285
286| Name| Value| Description|
287| ---- | - | ----------------- |
288| ACTION_DETECTING_STATUS | 0 | A drag gesture is being detected. (Triggered when the component is long pressed for 50 ms.)|
289| READY_TO_TRIGGER_DRAG_ACTION | 1 | The component is ready to be dragged. (Triggered when the component is long pressed for 500 ms.)|
290| PREVIEW_LIFT_STARTED | 2 | A lift animation is started. (Triggered when the component is long pressed for 800 ms.)|
291| PREVIEW_LIFT_FINISHED | 3 | A lift animation is finished. (Triggered at the completion of the lift animation.)|
292| PREVIEW_LANDING_STARTED | 4 | A drop animation is started. (Triggered when the drop animation starts.)|
293| PREVIEW_LANDING_FINISHED | 5 | A drop animation is finished. (Triggered when the drop animation ends.)|
294| 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.)|
295| 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.)|
296
297## executeDropAnimation<sup>18+</sup>
298
299Implements a custom drop animation execution function, which is only effective when **useCustomDropAnimation** is set to **true**.
300
301**Atomic service API**: This API can be used in atomic services since API version 18.
302
303**System capability**: SystemCapability.ArkUI.ArkUI.Full
304
305| Name    | Type | Description            |
306| ------ | ------ | ---------------- |
307| customDropAnimation | Callback\<void\>  |  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.|
308
309## DataSyncOptions<sup>15+</sup>
310
311type DataSyncOptions = GetDataParams
312
313Defines an input parameter for the **startDataLoading** API.
314
315**Atomic service API**: This API can be used in atomic services since API version 15.
316
317**System capability**: SystemCapability.ArkUI.ArkUI.Full
318
319| Type| Description|
320| ----- | ----------------- |
321| [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.|
322
323## Example
324
325### Example 1: Setting Draggable and Droppable Areas
326
327This example demonstrates the setup for draggable and droppable areas for certain components, such as **Image** and **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            // The result value obtained from onDragEnd is set in onDrop of the drop target.
410            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
411              promptAction.showToast({ duration: 100, message: 'Drag Success' });
412            } else if (event.getResult() === DragResult.DRAG_FAILED) {
413              promptAction.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              // If result is explicitly set to successful, the value is passed in to onDragEnd of the drag source.
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![events-drag-drop](figures/events-drag-drop.png)
522
523### Example 2: Implementing a Custom Drop Animation
524
525This example demonstrates how to implement a custom drop animation using the **executeDropAnimation** API.
526```ts
527import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
528import { promptAction } from '@kit.ArkUI';
529
530
531@Entry
532@Component
533struct DropAnimationExample {
534  @State targetImage: string = '';
535  @State targetText: string = 'Drag Text';
536  @State hyperLinkText: string = 'HyperLink';
537  @State hyperLinkContent: string = 'HyperLink';
538  @State imageWidth: number = 100;
539  @State imageHeight: number = 100;
540  @State imgState: Visibility = Visibility.Visible;
541  @State videoSrc: string = 'resource://RAWFILE/02.mp4';
542  @State abstractContent: string = "abstract";
543  @State textContent: string = "";
544
545  customDropAnimation =
546    () => {
547      this.getUIContext().animateTo({ duration: 1000, curve: Curve.EaseOut, playMode: PlayMode.Normal }, () => {
548        this.imageWidth = 200;
549        this.imageHeight = 200;
550        this.imgState = Visibility.None;
551      })
552    }
553
554  build() {
555    Row() {
556      Column() {
557        Image($r('app.media.app_icon'))
558          .width(100)
559          .height(100)
560          .draggable(true)
561          .margin({ left: 15 ,top: 40})
562          .visibility(this.imgState)
563          .onDragStart((event) => {
564          })
565          .onDragEnd((event) => {
566            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
567              promptAction.showToast({ duration: 100, message: 'Drag Success' });
568            } else if (event.getResult() === DragResult.DRAG_FAILED) {
569              promptAction.showToast({ duration: 100, message: 'Drag failed' });
570            }
571          })
572      }.width('45%')
573      .height('100%')
574      Column() {
575        Text('Drag Target Area')
576          .fontSize(20)
577          .width(180)
578          .height(40)
579          .textAlign(TextAlign.Center)
580          .margin(10)
581          .backgroundColor('rgb(240,250,255)')
582        Column() {
583          Image(this.targetImage)
584            .width(this.imageWidth)
585            .height(this.imageHeight)
586        }
587        .draggable(true)
588        .margin({ left: 15 })
589        .border({ color: Color.Black, width: 1 })
590        .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
591        .onDrop((dragEvent: DragEvent) => {
592          let records: Array<unifiedDataChannel.UnifiedRecord> = dragEvent.getData().getRecords();
593          let rect: Rectangle = dragEvent.getPreviewRect();
594          this.imageWidth = Number(rect.width);
595          this.imageHeight = Number(rect.height);
596          this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri;
597          dragEvent.useCustomDropAnimation = true;
598          dragEvent.executeDropAnimation(this.customDropAnimation)
599        })
600      }.width('45%')
601      .height('100%')
602      .margin({ left: '5%' })
603    }
604    .height('100%')
605  }
606}
607```
608![executeDropAnimation](figures/executeDropAnimation.gif)
609
610### Example 3: Obtaining Data Asynchronously Through Drag-and-Drop
611
612This example demonstrates how to asynchronously obtain data using **startDataLoading** during a drag-and-drop operation.
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  udKey: string = '';
625
626  build() {
627    Column() {
628      Text('Image drag and drop')
629        .fontSize('30dp')
630      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceAround }) {
631        Image($r('app.media.startIcon'))
632          .width(100)
633          .height(100)
634          .border({ width: 1 })
635          .draggable(true)
636          .onDragStart((event:DragEvent) => {
637            const context: Context = getContext(this);
638            let data = context.resourceManager.getMediaContentSync($r('app.media.startIcon').id, 120);
639            const arrayBuffer: ArrayBuffer = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset);
640            let filePath = context.filesDir + '/test.png';
641            let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
642            fs.writeSync(file.fd, arrayBuffer);
643            // Obtain the image URI.
644            let uri = fileUri.getUriFromPath(filePath);
645            let image: unifiedDataChannel.Image = new unifiedDataChannel.Image();
646            image.imageUri = uri;
647            let dragData: unifiedDataChannel.UnifiedData = new unifiedDataChannel.UnifiedData(image);
648            (event as DragEvent).setData(dragData);
649          })
650      }
651      .margin({ bottom: 20 })
652      Row() {
653        Column(){
654          Text('Valid drop target')
655            .fontSize('15dp')
656            .height('10%')
657          List(){
658            ForEach(this.blockArr, (item:string, index) => {
659              ListItem() {
660                Image(item)
661                  .width(100)
662                  .height(100)
663                  .border({width: 1})
664              }
665              .margin({ left: 30 , top : 30})
666            }, (item:string) => item)
667          }
668          .border({width: 1})
669          .height('90%')
670          .width('100%')
671          .onDrop((event?: DragEvent, extraParams?: string) => {
672            console.log("enter onDrop")
673            let context = getContext(this) as common.UIAbilityContext;
674            let pathDir: string = context.distributedFilesDir;
675            let destUri = fileUri.getUriFromPath(pathDir);
676            let progressListener: unifiedDataChannel.DataProgressListener = (progress: unifiedDataChannel.ProgressInfo, dragData: UnifiedData|null) => {
677              if(dragData != null) {
678                let arr:Array<unifiedDataChannel.UnifiedRecord> = dragData.getRecords();
679                if(arr.length > 0) {
680                  if (arr[0].getType() === uniformTypeDescriptor.UniformDataType.IMAGE) {
681                    let image = arr[0] as unifiedDataChannel.Image;
682                    this.uri = image.imageUri;
683                    this.blockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri);
684                  }
685                } else {
686                  console.log('dragData arr is null');
687                }
688              } else {
689                console.log('dragData is undefined');
690              }
691              console.log(`percentage: ${progress.progress}`);
692            };
693            let options: DataSyncOptions = {
694              destUri: destUri,
695              fileConflictOptions: unifiedDataChannel.FileConflictOptions.OVERWRITE,
696              progressIndicator: unifiedDataChannel.ProgressIndicator.DEFAULT,
697              dataProgressListener: progressListener,
698            }
699            try {
700              this.udKey = (event as DragEvent).startDataLoading(options);
701              console.log('udKey: ', this.udKey);
702            } catch(e) {
703              console.log(`startDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
704            }
705          }, {disableDataPrefetch: true})
706        }
707        .height("50%")
708        .width("90%")
709        .border({ width: 1 })
710      }
711      Button('Cancel data transfer')
712        .onClick(() => {
713          try {
714            this.getUIContext().getDragController().cancelDataLoading(this.udKey);
715          } catch (e) {
716            console.log(`cancelDataLoading errorCode: ${e.code}, errorMessage: ${e.message}`);
717          }
718        })
719        .margin({top: 10})
720    }.width('100%')
721  }
722}
723```
724<!--no_check-->