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<string> | 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 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 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 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 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