1# @ohos.arkui.dragController (DragController)
2
3The **dragController** module provides APIs for initiating drag actions. When receiving a gesture event, such as a touch or long-press event, an application can initiate a drag action and carry drag information therein.
4
5> **NOTE**
6>
7> The initial APIs of this module are supported since API version 10. Newly added APIs will be marked with a superscript to indicate their earliest API version.
8> The functionality of this module depends on UI context. This means that the APIs of this module cannot be used where the UI context is unclear. For details, see [UIContext](js-apis-arkui-UIContext.md#uicontext).
9> Since API version 10, you can use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in **UIContext** to obtain the **DragController** object associated with the current UI context.
10> You can preview how this component looks on a real device, but not in DevEco Studio Previewer.
11
12## Modules to Import
13
14```ts
15import { dragController } from "@kit.ArkUI";
16```
17
18## dragController.executeDrag
19
20executeDrag(custom: CustomBuilder | DragItemInfo, dragInfo: DragInfo,callback:AsyncCallback\<DragEventParam>): void
21
22Initiates a drag action, with the object to be dragged and the drag information passed in. This API uses an asynchronous callback to return the result.
23
24**Atomic service API**: This API can be used in atomic services since API version 12.
25
26**System capability**: SystemCapability.ArkUI.ArkUI.Full
27
28**Parameters**
29
30| Name  | Type                                                        | Mandatory| Description                                                        |
31| -------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
32| custom   | [CustomBuilder](arkui-ts/ts-types.md#custombuilder8) \| [DragItemInfo](arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo) | Yes  | Object to be dragged.<br>**NOTE**<br>The global builder is not supported. If the [Image](arkui-ts/ts-basic-components-image.md) component is used in the builder, enable synchronous loading, that is, set the [syncLoad](arkui-ts/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.|
33| dragInfo | [DragInfo](#draginfo)                                        | Yes  | Drag information.                                                  |
34| callback | [AsyncCallback](../apis-basic-services-kit/js-apis-base.md#asynccallback)&lt;[DragEventParam](#drageventparam12)&gt; | Yes  | Callback used to return the result.                                    |
35
36**Error codes**
37
38For details about the error codes, see [Universal Error Codes](../errorcode-universal.md).
39
40| ID| Error Message     |
41| -------- | ------------- |
42| 401      | Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; 2.Incorrect parameters types; 3. Parameter verification failed.   |
43| 100001   | Internal handling failed. |
44
45**Example**
46
47> **NOTE**
48>
49> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
50
51```ts
52import { dragController } from "@kit.ArkUI";
53import { unifiedDataChannel } from '@kit.ArkData';
54
55@Entry
56@Component
57struct DragControllerPage {
58  @State text: string = ''
59
60  @Builder DraggingBuilder() {
61    Column() {
62      Text("DraggingBuilder")
63        .fontColor(Color.White)
64        .fontSize(12)
65    }
66    .width(100)
67    .height(100)
68    .backgroundColor(Color.Blue)
69  }
70
71  build() {
72    Column() {
73      Button('touch to execute drag')
74        .margin(10)
75        .onTouch((event?:TouchEvent) => {
76          if(event){
77            if (event.type == TouchType.Down) {
78              let text = new unifiedDataChannel.PlainText()
79              text.textContent = 'drag text'
80              text.abstract = 'abstract'
81              let unifiedData = new unifiedDataChannel.UnifiedData(text)
82
83              let dragInfo: dragController.DragInfo = {
84                pointerId: 0,
85                data: unifiedData,
86                extraParams: ''
87              }
88              class tmp{
89                event:DragEvent|undefined = undefined
90                extraParams:string = ''
91              }
92              let eve:tmp = new tmp()
93              dragController.executeDrag(()=>{this.DraggingBuilder()}, dragInfo, (err, eve) => { // You are advised to use this.getUIContext().getDragController().executeDrag().
94                if(eve.event){
95                  if (eve.event.getResult() == DragResult.DRAG_SUCCESSFUL) {
96                    // ...
97                  } else if (eve.event.getResult() == DragResult.DRAG_FAILED) {
98                    // ...
99                  }
100                }
101              })
102            }
103          }
104        })
105      Text(this.text)
106        .height(100)
107        .width(150)
108        .margin({top:20})
109        .border({color:Color.Black,width:1})
110        .onDrop((dragEvent?:DragEvent)=>{
111          if(dragEvent){
112            let records: Array<unifiedDataChannel.UnifiedRecord> = dragEvent.getData().getRecords();
113            let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
114            this.text = plainText.textContent;
115          }
116        })
117    }
118    .width('100%')
119    .height('100%')
120  }
121}
122```
123  ![en-us_executeDrag1](figures/executeDrag1.gif)
124## dragController.executeDrag
125
126executeDrag(custom: CustomBuilder | DragItemInfo, dragInfo: DragInfo): Promise\<DragEventParam>
127
128Initiates a drag action, with the object to be dragged and the drag information passed in. This API uses a promise to return the result.
129
130**Atomic service API**: This API can be used in atomic services since API version 12.
131
132**System capability**: SystemCapability.ArkUI.ArkUI.Full
133
134**Parameters**
135
136| Name  | Type                                                        | Mandatory| Description                            |
137| -------- | ------------------------------------------------------------ | ---- | -------------------------------- |
138| custom   | [CustomBuilder](arkui-ts/ts-types.md#custombuilder8) \| [DragItemInfo](arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo) | Yes  | Object to be dragged.|
139| dragInfo | [DragInfo](#draginfo)                                        | Yes  | Drag information.                      |
140
141**Return value**
142
143| Type                                              | Description                    |
144| -------------------------------------------------- | ------------------------ |
145| Promise&lt;[DragEventParam](#drageventparam12)&gt; | Promise used to return the result.|
146
147**Error codes**
148For details about the error codes, see [Universal Error Codes](../errorcode-universal.md).
149| ID| Error Message     |
150| -------- | ------------- |
151| 401      | Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; 2.Incorrect parameters types; 3. Parameter verification failed.   |
152| 100001   | Internal handling failed. |
153
154**Example**
155
156> **NOTE**
157>
158> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
159
160```ts
161import { dragController, componentSnapshot } from "@kit.ArkUI"
162import { image } from '@kit.ImageKit';
163import { unifiedDataChannel } from '@kit.ArkData';
164
165@Entry
166@Component
167struct DragControllerPage {
168  @State pixmap: image.PixelMap|undefined = undefined
169  @State text: string = ''
170
171  @Builder DraggingBuilder() {
172    Column() {
173      Text("DraggingBuilder")
174        .fontColor(Color.White)
175    }
176    .width(100)
177    .height(100)
178    .backgroundColor(Color.Blue)
179  }
180
181  @Builder PixmapBuilder() {
182    Column() {
183      Text("PixmapBuilder")
184        .fontColor(Color.White)
185        .fontSize(15)
186    }
187    .width(100)
188    .height(100)
189    .backgroundColor(Color.Blue)
190  }
191
192  aboutToAppear() {
193    let pb: CustomBuilder = (): void => {
194      this.PixmapBuilder()
195    }
196    componentSnapshot.createFromBuilder(pb).then((pix: image.PixelMap) => {
197      this.pixmap = pix;
198    })
199  }
200
201  build() {
202    Column() {
203      Button('touch to execute drag')
204        .margin(10)
205        .onTouch((event?:TouchEvent) => {
206          if(event){
207            if (event.type == TouchType.Down) {
208              let text = new unifiedDataChannel.PlainText()
209              text.textContent = 'drag text'
210              text.abstract = 'abstract'
211              let unifiedData = new unifiedDataChannel.UnifiedData(text)
212
213              let dragInfo: dragController.DragInfo = {
214                pointerId: 0,
215                data: unifiedData,
216                extraParams: ''
217              }
218              let dragItemInfo: DragItemInfo = {
219                pixelMap: this.pixmap,
220                builder: ()=>{this.DraggingBuilder()},
221                extraInfo: "DragItemInfoTest"
222              }
223
224              class tmp{
225                event:DragResult|undefined = undefined
226                extraParams:string = ''
227              }
228              let eve:tmp = new tmp()
229              dragController.executeDrag(dragItemInfo, dragInfo) // You are advised to use this.getUIContext().getDragController().executeDrag().
230                .then((eve) => {
231                  if (eve.event.getResult() == DragResult.DRAG_SUCCESSFUL) {
232                    // ...
233                  } else if (eve.event.getResult() == DragResult.DRAG_FAILED) {
234                    // ...
235                  }
236                })
237                .catch((err:Error) => {
238                })
239            }
240          }
241        })
242      Text(this.text)
243        .height(100)
244        .width(150)
245        .margin({top:20})
246        .border({color:Color.Black,width:1})
247        .onDrop((dragEvent?:DragEvent)=>{
248          if(dragEvent){
249            let records: Array<unifiedDataChannel.UnifiedRecord> = dragEvent.getData().getRecords();
250            let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
251            this.text = plainText.textContent;
252          }
253        })
254    }
255    .width('100%')
256    .height('100%')
257  }
258}
259```
260  ![en-us_executeDrag2](figures/executeDrag2.gif)
261## DragInfo
262
263**Atomic service API**: This API can be used in atomic services since API version 12.
264
265**System capability**: SystemCapability.ArkUI.ArkUI.Full
266
267Defines the attributes required for initiating a drag action and information carried in the dragging process.
268
269| Name       | Type                                                  | Mandatory| Description                                    |
270| ----------- | ------------------------------------------------------ | ---- | ---------------------------------------- |
271| pointerId   | number                                                 | Yes  | ID of the touch point on the screen when dragging is started.        |
272| data        | [unifiedDataChannel.UnifiedData](../apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata) | No  | Data carried in the dragging process.              |
273| extraParams | string                                                 | No  | Additional information about the drag action. Not supported currently.|
274| touchPoint<sup>11+</sup>    | [TouchPoint](arkui-ts/ts-types.md#touchpoint11)  | No  | Coordinates of the touch point. If this parameter is not set, the touch point is centered.|
275| previewOptions<sup>11+</sup>| [DragPreviewOptions](arkui-ts/ts-universal-attributes-drag-drop.md#dragpreviewoptions11)                                | No  | Custom configuration of the drag preview.|
276
277## dragController.createDragAction<sup>11+</sup>
278
279createDragAction(customArray: Array&lt;CustomBuilder \| DragItemInfo&gt;, dragInfo: DragInfo): DragAction
280
281Creates a drag action object for initiating drag and drop operations. You need to explicitly specify one or more drag previews, the drag data, and the drag handle point. If a drag operation initiated by an existing drag action object is not completed, no new object can be created, and calling the API will throw an exception. After the lifecycle of the drag action object ends, the callback functions registered on this object become invalid. Therefore, it is necessary to hold this object within a longer scope and replace the old value with a new object returned by **createDragAction** before each drag initiation.
282
283**NOTE**<br>You are advised to control the number of drag previews. If too many previews are passed in, the drag efficiency may be affected.
284
285**Atomic service API**: This API can be used in atomic services since API version 12.
286
287**System capability**: SystemCapability.ArkUI.ArkUI.Full
288
289**Parameters**
290
291| Name  | Type                                                        | Mandatory| Description                            |
292| --------      | ------------------------------------------------------------ | ---- | -------------------------------- |
293| customArray  | Array&lt;[CustomBuilder](arkui-ts/ts-types.md#custombuilder8) \| [DragItemInfo](arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo)&gt; | Yes  | Object to be dragged.|
294| dragInfo | [DragInfo](#draginfo)                                        | Yes  | Drag information.                      |
295
296**Return value**
297
298| Type                                                  | Description              |
299| ------------------------------------------------------ | ------------------ |
300| [DragAction](#dragaction11)| **DragAction** object, which is used to subscribe to drag state changes and start the drag service.|
301
302**Error codes**
303
304For details about the error codes, see [Universal Error Codes](../errorcode-universal.md).
305| ID| Error Message     |
306| -------- | ------------- |
307| 401      | Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; 2.Incorrect parameters types; 3. Parameter verification failed.   |
308| 100001   | Internal handling failed. |
309
310**Example**
311
312> **NOTE**
313>
314> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
315
316```ts
317import { dragController, componentSnapshot } from "@kit.ArkUI";
318import { image } from '@kit.ImageKit';
319import { unifiedDataChannel } from '@kit.ArkData';
320
321@Entry
322@Component
323struct DragControllerPage {
324  @State pixmap: image.PixelMap | null = null
325  @State text: string = ''
326  private dragAction: dragController.DragAction | null = null;
327  customBuilders:Array<CustomBuilder | DragItemInfo> = new Array<CustomBuilder | DragItemInfo>();
328  @Builder DraggingBuilder() {
329    Column() {
330      Text("DraggingBuilder")
331        .fontColor(Color.White)
332        .fontSize(12)
333    }
334    .width(100)
335    .height(100)
336    .backgroundColor(Color.Blue)
337  }
338
339  build() {
340    Column() {
341
342      Column() {
343        Text(this.text)
344          .width('100%')
345          .height('100%')
346          .fontColor(Color.White)
347          .fontSize(18)
348          .onDrop((dragEvent?:DragEvent)=>{
349            if(dragEvent){
350              let records: Array<unifiedDataChannel.UnifiedRecord> = dragEvent.getData().getRecords();
351              let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
352              this.text = plainText.textContent;
353            }
354          })
355      }
356      .width(100)
357      .height(100)
358      .backgroundColor(Color.Red)
359      .margin(10)
360
361      Button('Drag Multiple Objects').onTouch((event?:TouchEvent) => {
362        if(event){
363          if (event.type == TouchType.Down) {
364            console.info("muti drag Down by listener");
365            this.customBuilders.splice(0, this.customBuilders.length);
366            this.customBuilders.push(()=>{this.DraggingBuilder()});
367            this.customBuilders.push(()=>{this.DraggingBuilder()});
368            this.customBuilders.push(()=>{this.DraggingBuilder()});
369            let text = new unifiedDataChannel.PlainText()
370            text.textContent = 'drag text'
371            let unifiedData = new unifiedDataChannel.UnifiedData(text)
372            let dragInfo: dragController.DragInfo = {
373              pointerId: 0,
374              data: unifiedData,
375              extraParams: ''
376            }
377            try{
378              this.dragAction = dragController.createDragAction(this.customBuilders, dragInfo) // You are advised to use this.getUIContext().getDragController().createDragAction().
379              if(!this.dragAction){
380                console.info("listener dragAction is null");
381                return
382              }
383              this.dragAction.on('statusChange', (dragAndDropInfo: dragController.DragAndDropInfo)=>{
384                if (dragAndDropInfo.status == dragController.DragStatus.STARTED) {
385                  console.info("drag has start");
386                } else if (dragAndDropInfo.status == dragController.DragStatus.ENDED){
387                  console.info("drag has end");
388                  if (!this.dragAction) {
389                    return
390                  }
391                  this.dragAction.off('statusChange')
392                }
393              })
394              this.dragAction.startDrag().then(()=>{}).catch((err:Error)=>{
395                console.info("start drag Error:" + err.message);
396              })
397            } catch(err) {
398              console.info("create dragAction Error:" + err.message);
399            }
400          }
401        }
402      }).margin({top:20})
403    }
404  }
405}
406```
407  ![en-us_executeDrag3](figures/executeDrag3.gif)
408## DragAction<sup>11+</sup>
409
410Implements a **DragAction** object to subscribe to drag state changes and start the drag service.
411
412**Atomic service API**: This API can be used in atomic services since API version 12.
413
414**System capability**: SystemCapability.ArkUI.ArkUI.Full
415
416### startDrag<sup>11+</sup>
417
418startDrag(): Promise&lt;void&gt;
419
420Starts the drag service. This API uses a promise to return the result.
421
422**Atomic service API**: This API can be used in atomic services since API version 12.
423
424**System capability**: SystemCapability.ArkUI.ArkUI.Full
425
426**Error codes**
427
428| ID| Error Message     |
429| -------- | ------------- |
430| 100001   | Internal handling failed. |
431
432**Example**
433
434> **NOTE**
435>
436> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
437
438```ts
439import { dragController } from "@kit.ArkUI"
440import { unifiedDataChannel } from '@kit.ArkData';
441
442@Entry
443@Component
444struct DragControllerPage {
445  build() {
446    Column() {
447      Button('touch to execute drag')
448        .onTouch((event?:TouchEvent) => {
449          let customBuilders:Array<CustomBuilder | DragItemInfo> = new Array<CustomBuilder | DragItemInfo>();
450          let text = new unifiedDataChannel.Text()
451          let unifiedData = new unifiedDataChannel.UnifiedData(text)
452          let dragInfo: dragController.DragInfo = {
453            pointerId: 0,
454            data: unifiedData,
455            extraParams: ''
456          }
457          try {
458            let dragAction: dragController.DragAction | null = dragController.createDragAction(customBuilders, dragInfo); // You are advised to use this.getUIContext().getDragController().createDragAction().
459            if(!dragAction){
460              console.info("listener dragAction is null");
461              return
462            }
463            dragAction.startDrag().then(()=>{}).catch((err:Error)=>{
464              console.info("start drag Error:" + err.message);
465            })
466          } catch (err) {
467            console.info("create dragAction Error:" + err.message);
468          }
469        })
470    }
471  }
472}
473
474```
475
476### on('statusChange')<sup>11+</sup>
477
478on(type: 'statusChange', callback: Callback&lt;[DragAndDropInfo](#draganddropinfo11)&gt;): void
479
480Subscribes to drag state changes.
481
482**Atomic service API**: This API can be used in atomic services since API version 12.
483
484**System capability**: SystemCapability.ArkUI.ArkUI.Full
485
486**Parameters**
487| Name    | Type | Mandatory   | Description            |
488| ------ | ------ | ------- | ---------------- |
489|  type  | string | Yes     | Event type. The value is fixed at **'statusChange'**, which indicates the drag state change event.|
490|  callback  | Callback&lt;[DragAndDropInfo](#draganddropinfo11)&gt; | Yes     | Callback used to return a [DragAndDropInfo](#draganddropinfo11) instance.|
491
492**Example**
493
494> **NOTE**
495>
496> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
497
498```ts
499import { dragController } from "@kit.ArkUI";
500import { unifiedDataChannel } from '@kit.ArkData';
501
502@Entry
503@Component
504struct DragControllerPage {
505  build() {
506    Column() {
507      Button('touch to execute drag')
508        .onTouch((event?:TouchEvent) => {
509          let customBuilders:Array<CustomBuilder | DragItemInfo> = new Array<CustomBuilder | DragItemInfo>();
510          let text = new unifiedDataChannel.Text()
511          let unifiedData = new unifiedDataChannel.UnifiedData(text)
512          let dragInfo: dragController.DragInfo = {
513            pointerId: 0,
514            data: unifiedData,
515            extraParams: ''
516          }
517          try{
518            let dragAction: dragController.DragAction | null = dragController.createDragAction(customBuilders, dragInfo); // You are advised to use this.getUIContext().getDragController().createDragAction().
519            if(!dragAction){
520              console.info("listener dragAction is null");
521              return
522            }
523            dragAction.on('statusChange', (dragAndDropInfo: dragController.DragAndDropInfo)=>{
524              console.info("Register to listen on drag status", JSON.stringify(dragAndDropInfo));
525            })
526          }catch(err) {
527            console.info("create dragAction Error:" + err.message);
528          }
529        })
530    }
531  }
532}
533```
534
535### off('statusChange')<sup>11+</sup>
536
537 off(type: 'statusChange', callback?: Callback&lt;[DragAndDropInfo](#draganddropinfo11)&gt;): void
538
539Unsubscribes from drag state changes.
540
541**Atomic service API**: This API can be used in atomic services since API version 12.
542
543**System capability**: SystemCapability.ArkUI.ArkUI.Full
544
545**Parameters**
546| Name    | Type | Mandatory   | Description            |
547| ------ | ------ | ------- | ---------------- |
548|  type  | string | Yes     | Event type. The value is fixed at **'statusChange'**, which indicates the drag state change event.|
549|  callback  | Callback&lt;[DragAndDropInfo](#draganddropinfo11)&gt; | No     | Callback used to return a [DragAndDropInfo](#draganddropinfo11) instance. If this parameter is not set, this API unsubscribes from all callbacks corresponding to **type**.|
550
551**Example**
552
553> **NOTE**
554>
555> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
556
557```ts
558import { dragController } from "@kit.ArkUI"
559import { unifiedDataChannel } from '@kit.ArkData';
560
561@Entry
562@Component
563struct DragControllerPage {
564  build() {
565    Column() {
566      Button('touch to execute drag')
567        .onTouch((event?:TouchEvent) => {
568          let customBuilders:Array<CustomBuilder | DragItemInfo> = new Array<CustomBuilder | DragItemInfo>();
569          let text = new unifiedDataChannel.Text()
570          let unifiedData = new unifiedDataChannel.UnifiedData(text)
571          let dragInfo: dragController.DragInfo = {
572            pointerId: 0,
573            data: unifiedData,
574            extraParams: ''
575          }
576          try{
577            let dragAction: dragController.DragAction | null = dragController.createDragAction(customBuilders, dragInfo); // You are advised to use this.getUIContext().getDragController().createDragAction().
578            if(!dragAction){
579              console.info("listener dragAction is null");
580              return
581            }
582            dragAction.off('statusChange', (dragAndDropInfo: dragController.DragAndDropInfo)=>{
583              console.info("Cancel listening on drag status", JSON.stringify(dragAndDropInfo));
584            })
585          }catch(err) {
586            console.info("create dragAction Error:" + err.message);
587          }
588        })
589    }
590  }
591}
592```
593
594## DragAndDropInfo<sup>11+</sup>
595
596**Atomic service API**: This API can be used in atomic services since API version 12.
597
598**System capability**: SystemCapability.ArkUI.ArkUI.Full
599
600Provides the data reported when the state changes during dragging.
601
602| Name         | Type                                                  | Mandatory| Description                                    |
603| -----------   | ------------------------------------------------------ | ---- | ---------------------------------------- |
604| status       | [DragStatus](#dragstatus11)                                                 | Yes  | Current dragging state (started or ended).        |
605| event        | [DragEvent](arkui-ts/ts-universal-events-drag-drop.md#dragevent) | Yes  | Drag event corresponding to the current state.              |
606| extraParams| string                                                 | No  | Additional information about the drag action. Not supported currently.|
607
608## DragStatus<sup>11+</sup>
609
610**Atomic service API**: This API can be used in atomic services since API version 12.
611
612**System capability**: SystemCapability.ArkUI.ArkUI.Full
613
614Describes the dragging start and end states.
615
616| Name         | Value                                                  | Description                                    |
617| -----------   | ------------------------------------------------------| ---------------------------------------- |
618| STARTED       | 0                                                  | Dragging is started.        |
619| ENDED        | 1                                                  | Dragging ends.              |
620
621## AnimationOptions<sup>11+</sup>
622
623**Atomic service API**: This API can be used in atomic services since API version 12.
624
625**System capability**: SystemCapability.ArkUI.ArkUI.Full
626
627Defines the attributes required for initiating a drag action and information carried in the dragging process.
628
629| Name       | Type                                                  | Mandatory| Description                                    |
630| ----------- | ------------------------------------------------------ | ---- | ---------------------------------------- |
631| duration    | number                                                 | No  | Animation duration, in ms.<br>Default value: **1000**<br>**NOTE**<br>- If this parameter is set to a value less than 0, the value **0** is used.<br>- Floating-point values will be rounded down to integers. For example, if the value set is 1.2, **1** will be used.|
632| curve       | [Curve](arkui-ts/ts-appendix-enums.md#curve) \| [ICurve](js-apis-curve.md#icurve9) | No   | Animation curve.<br>Default value: **Curve.EaseInOut**|                          |
633
634## DragEventParam<sup>12+</sup>
635
636**Atomic service API**: This API can be used in atomic services since API version 12.
637
638**System capability**: SystemCapability.ArkUI.ArkUI.Full
639
640Represents the callback used to return the result after a drag ends.
641
642| Name       | Type                                                        | Mandatory| Description                          |
643| ----------- | ------------------------------------------------------------ | ---- | ------------------------------ |
644| event       | [DragEvent](arkui-ts/ts-universal-events-drag-drop.md#dragevent) | Yes  | Drag event information that includes only the drag result.|
645| extraParams | string                                                       | Yes  | Additional information about the drag event.            |
646
647## dragController.getDragPreview<sup>11+</sup>
648
649getDragPreview(): DragPreview
650
651Obtains the **DragPreview** object, which represents the preview displayed during a drag.
652
653**Atomic service API**: This API can be used in atomic services since API version 12.
654
655**System capability**: SystemCapability.ArkUI.ArkUI.Full
656
657**Return value**
658
659| Type       | Description                                           |
660| ------------| ------------------------------------------------|
661| [DragPreview](#dragpreview11) | **DragPreview** object. It provides the API for setting the preview style. It does not work in the **OnDrop** and **OnDragEnd** callbacks.|
662
663**Example**
664
665For details, see [animate](#animate11).
666
667## DragPreview<sup>11+</sup>
668
669Implements a **DragPreview** object. This API does not work in the **OnDrop** and **OnDragEnd** callbacks.
670
671**Atomic service API**: This API can be used in atomic services since API version 12.
672
673**System capability**: SystemCapability.ArkUI.ArkUI.Full
674
675### setForegroundColor<sup>11+</sup>
676
677setForegroundColor(color: ResourceColor): void
678
679Sets the foreground color of the drag preview. This API does not work in the **OnDrop** and **OnDragEnd** callbacks. It can only be used on the object obtained through the [getDragPreview()](js-apis-arkui-UIContext.md#getdragpreview11) API.
680
681**Atomic service API**: This API can be used in atomic services since API version 12.
682
683**System capability**: SystemCapability.ArkUI.ArkUI.Full
684
685**Parameters**
686
687| Name  | Type                            | Mandatory| Description                    |
688| -------- | -------------------------------- | ---- | ------------------------ |
689| color    | [ResourceColor](arkui-ts/ts-types.md#resourcecolor) | Yes  |      Foreground color of the drag preview.                   |
690
691**Example**
692
693For details, see [animate](#animate11).
694
695  ### animate<sup>11+</sup>
696
697animate(options: AnimationOptions, handler: () => void): void
698
699Applies a foreground color animation to the drag preview. This API does not work in the **OnDrop** and **OnDragEnd** callbacks. It can only be used on the object obtained through the [getDragPreview()](js-apis-arkui-UIContext.md#getdragpreview11) API.
700
701**Atomic service API**: This API can be used in atomic services since API version 12.
702
703**System capability**: SystemCapability.ArkUI.ArkUI.Full
704
705**Parameters**
706
707| Name  | Type                            | Mandatory| Description                              |
708| -------- | -------------------------------- | ---- | -----------------------------------|
709| options  | [AnimationOptions](#animationoptions11)                | Yes  | Animation settings.                          |
710| handler  | () => void                         | Yes  | Callback used to change attributes such as the background mask color. |
711
712**Example**
713
714> **NOTE**
715>
716> You are advised to use the [getDragController](js-apis-arkui-UIContext.md#getdragcontroller11) API in [UIContext](js-apis-arkui-UIContext.md#uicontext) to obtain the **DragController** object associated with the current UI context.
717
7181. In the **EntryAbility.ets** file, obtain the UI context and save it to LocalStorage.
719  ```ts
720import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
721import { hilog } from '@kit.PerformanceAnalysisKit';
722import { window, UIContext } from '@kit.ArkUI';
723
724let uiContext: UIContext;
725let localStorage: LocalStorage = new LocalStorage('uiContext');
726
727export default class EntryAbility extends UIAbility {
728  storage: LocalStorage = localStorage;
729
730  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
731    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
732  }
733
734  onDestroy(): void {
735    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
736  }
737
738  onWindowStageCreate(windowStage: window.WindowStage): void {
739    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
740
741    windowStage.loadContent('pages/Index', (err, data) => {
742      if (err.code) {
743        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
744        return;
745      }
746      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
747      windowStage.getMainWindow((err, data) => {
748        if (err.code) {
749          hilog.error(0x0000, 'Failed to abtain the main window. Cause:' + err.message, '');
750          return;
751        }
752        let windowClass: window.Window = data;
753        uiContext = windowClass.getUIContext();
754        this.storage.setOrCreate<UIContext>('uiContext', uiContext);
755      })
756    });
757  }
758}
759  ```
7602. In the **Index.ets** file, call **LocalStorage.getShared()** to obtain the UI context and then use the **DragController** object obtained to perform subsequent operations.
761  ```ts
762
763import { unifiedDataChannel } from '@kit.ArkData';
764import { hilog } from '@kit.PerformanceAnalysisKit';
765import { dragController, curves, promptAction, UIContext } from "@kit.ArkUI";
766import { image } from '@kit.ImageKit';
767import { BusinessError } from '@kit.BasicServicesKit';
768
769let storages = LocalStorage.getShared();
770
771@Entry(storages)
772@Component
773struct DragControllerPage {
774  @State pixmap: image.PixelMap|null = null
775
776  @Builder DraggingBuilder() {
777    Column() {
778      Text("DraggingBuilder")
779        .fontColor(Color.White)
780        .fontSize(12)
781    }
782    .width(100)
783    .height(100)
784    .backgroundColor(Color.Blue)
785  }
786
787  @Builder PixmapBuilder() {
788    Column() {
789      Text("PixmapBuilder")
790    }
791    .width(100)
792    .height(100)
793    .backgroundColor(Color.Blue)
794  }
795
796  build() {
797    Column() {
798      Button ('Drag Here')
799        .margin(10)
800        .onDragEnter(() => {
801        try {
802          let uiContext: UIContext = storages.get<UIContext>('uiContext') as UIContext;
803          let previewObj: dragController.DragPreview = uiContext.getDragController().getDragPreview();
804          let foregroundColor: ResourceColor = Color.Green;
805
806          let previewAnimation: dragController.AnimationOptions = {
807            curve: curves.cubicBezierCurve(0.2,0,0,1),
808          }
809          previewObj.animate(previewAnimation, () => {
810            previewObj.setForegroundColor(foregroundColor);
811          });
812        } catch (error) {
813          let msg = (error as BusinessError).message;
814          let code = (error as BusinessError).code;
815          hilog.error(0x0000, `show error code is ${code}, message is ${msg}`, '');
816        }
817      })
818        .onDrop(() => {
819          promptAction.showToast({duration: 100, message: 'Drag Success', bottom: 400})
820        })
821      Button ('Drag').onTouch ((event?:TouchEvent) => {
822        if(event){
823          if (event.type == TouchType.Down) {
824            let text = new unifiedDataChannel.Text()
825            let unifiedData = new unifiedDataChannel.UnifiedData(text)
826            let dragInfo: dragController.DragInfo = {
827              pointerId: 0,
828              data: unifiedData,
829              extraParams: ''
830            }
831            class tmp{
832              event:DragEvent|undefined = undefined
833              extraParams:string = ''
834            }
835            let eve:tmp = new tmp()
836            dragController.executeDrag(() => { // You are advised to use this.getUIContext().getDragController().executeDrag().
837              this.DraggingBuilder()
838            }, dragInfo, (err , eve) => {
839              hilog.info(0x0000, `ljx ${JSON.stringify(err)}`, '')
840              if (eve && eve.event) {
841                if (eve.event.getResult() == DragResult.DRAG_SUCCESSFUL) {
842                  hilog.info(0x0000, 'success', '');
843                } else if (eve.event.getResult() == DragResult.DRAG_FAILED) {
844                  hilog.info(0x0000, 'failed', '');
845                }
846              }
847            })
848          }
849        }
850      }).margin({top:100})
851    }
852    .width('100%')
853    .height('100%')
854  }
855}
856  ```
857  ![en-us_executeDrag5](figures/executeDrag5.gif)
858