• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Drag Event
2
3A drag event is triggered when a component is dragged.
4
5>  **NOTE**
6>
7>  This feature is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
8>
9> The resource files preset in the application (that is, the resource files that are contained in the HAP file before the application is installed) can be dragged and dropped only within the application.
10
11The ArkUI framework implements the drag and drop capability 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). To enable drag and drop for these components, you only need to set their [draggable](ts-universal-attributes-drag-drop.md) attribute to **true**.
12
13- The following component supports drag operations by default: **\<Search>**, **\<TextInput>**, **\<TextArea>**, **\<RichEditor>**, **\<Text>**, **\<Image>**, **\<FormComponent>**, **\<Hyperlink>**
14
15- The following component supports drop operations by default: **\<Search>**, **\<TextInput>**, **\<TextArea>**, **\<Video>**
16
17You can also define drag responses by implementing common drag events.
18
19To 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**.
20
21## onDragStart
22
23onDragStart(event: (event: DragEvent, extraParams?: string) => CustomBuilder | DragItemInfo)
24
25Triggered 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 longer.
26
27**Event priority**:<br>Long press time < 500 ms: Long press event > Drag event<br>Other cases: Drag event > Long press event
28
29**System capability**: SystemCapability.ArkUI.ArkUI.Full
30
31**Parameters**
32
33| Name     | Type                           | Mandatory| Description              |
34| ----------- | ------------------------------- | ---- | ------------------ |
35| event       | [DragEvent](#dragevent)     | Yes  | Information about the drag event.    |
36| extraParams | [extraParams](#extraparams) | No  | Additional information about the drag event.|
37
38**Return value**
39
40| Type                                                        | Description                    |
41| ------------------------------------------------------------ | ------------------------ |
42| [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo) | Component information displayed during dragging.<br>**NOTE**<br>The global builder is not supported.|
43
44## onDragEnter
45
46onDragEnter(event: (event: DragEvent, extraParams?: string) => void)
47
48Triggered when the dragged item enters a valid drop target. This event is valid only when a listener for the [onDrop](#ondrop) event is enabled.
49
50**System capability**: SystemCapability.ArkUI.ArkUI.Full
51
52**Parameters**
53
54| Name     | Type                           | Mandatory| Description                          |
55| ----------- | ------------------------------- | ---- | ------------------------------ |
56| event       | [DragEvent](#dragevent)     | Yes  | Information about the drag event, including the coordinates of the item that is being dragged.|
57| extraParams | [extraParams](#extraparams) | No  | Additional information about the drag event.            |
58
59## onDragMove
60
61onDragMove(event: (event: DragEvent, extraParams?: string) => void)
62
63Triggered when the dragged item moves in a valid drop target. This event is valid only when a listener for the [onDrop](#ondrop) event is enabled.
64
65**System capability**: SystemCapability.ArkUI.ArkUI.Full
66
67**Parameters**
68
69| Name     | Type                           | Mandatory| Description                          |
70| ----------- | ------------------------------- | ---- | ------------------------------ |
71| event       | [DragEvent](#dragevent)     | Yes  | Information about the drag event, including the coordinates of the item that is being dragged.|
72| extraParams | [extraParams](#extraparams) | No  | Additional information about the drag event.            |
73
74## onDragLeave
75
76onDragLeave(event: (event: DragEvent, extraParams?: string) => void)
77
78Triggered when the dragged item leaves a valid drop target. This event is valid only when a listener for the [onDrop](#ondrop) event is enabled.
79
80**System capability**: SystemCapability.ArkUI.ArkUI.Full
81
82**Parameters**
83
84| Name     | Type                           | Mandatory| Description                          |
85| ----------- | ------------------------------- | ---- | ------------------------------ |
86| event       | [DragEvent](#dragevent)     | Yes  | Information about the drag event, including the coordinates of the item that is being dragged.|
87| extraParams | [extraParams](#extraparams) | No  | Additional information about the drag event.            |
88
89## onDrop
90
91onDrop(event: (event: DragEvent, extraParams?: string) => void)
92
93Triggered when the dragged item is dropped on a valid drop target. If **event.setResult()** is not explicitly used, the default value **DRAG_SUCCESSFUL** will be used as the result.
94
95**System capability**: SystemCapability.ArkUI.ArkUI.Full
96
97**Parameters**
98
99| Name     | Type                           | Mandatory| Description                          |
100| ----------- | ------------------------------- | ---- | ------------------------------ |
101| event       | [DragEvent](#dragevent)     | Yes  | Information about the drag event, including the coordinates of the item that is being dragged.|
102| extraParams | [extraParams](#extraparams) | No  | Additional information about the drag event.            |
103
104## onDragEnd
105
106onDragEnd(event: (event: DragEvent, extraParams?: string) => void)
107
108Triggered when the dragging of the component bound to the event ends.
109
110**System capability**: SystemCapability.ArkUI.ArkUI.Full
111
112**Parameters**
113
114| Name     | Type                           | Mandatory| Description                          |
115| ----------- | ------------------------------- | ---- | ------------------------------ |
116| event       | [DragEvent](#dragevent)     | Yes  | Information about the drag event, including the coordinates of the item that is being dragged.|
117| extraParams | [extraParams](#extraparams) | No  | Additional information about the drag event.            |
118
119## DragItemInfo
120
121| Name     | Type                                    | Mandatory  | Description                               |
122| --------- | ---------------------------------------- | ---- | --------------------------------- |
123| pixelMap  | [PixelMap](../apis/js-apis-image.md#pixelmap7) | No   | Image to be displayed during dragging.                    |
124| builder   | [CustomBuilder](ts-types.md#custombuilder8) | No   | Custom component to display during dragging. If **pixelMap** is set, this attribute is ignored.<br> **NOTE**<br>Global builder definition 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#attributes) attribute of the component to **true**.|
125| extraInfo | string                                   | No   | Extra information of the dragged item.                          |
126
127
128## extraParams
129
130  Provides additional information required for dragging an item.
131
132  **extraParams** is a string converted from a JSON object. You can obtain the following attributes using the JSON object converted from **Json.parse**.
133
134| Name         | Type  | Description                                      |
135| ------------- | ------ | ---------------------------------------- |
136| selectedIndex | number | Index of the dragged item in the parent container. The value of **selectedindex** starts from **0**.<br>This parameter is valid only in the drag event of the **\<ListItem>** component.|
137| 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 is valid only in the drag event of the **\<List>** component.|
138
139## DragEvent
140
141### Attributes
142
143| Name    | Type | Description            |
144| ------ | ------ | ---------------- |
145| useCustomDropAnimation<sup>10+</sup> | boolean | Whether to use the custom drop animation when the dragging ends.<br>If this parameter is set to **true**, the default drop animation is disabled, and the custom one is used.<br>If this parameter is set to **false** or is not set, the default drop animation is enabled. In this case, to avoid conflicts, the application should not implement any custom drop animation.|
146|dragBehavior<sup>10+</sup> | [DragBehavior](#dragbehavior10) | Copy or paste mode.|
147
148### Methods
149
150| Name    | Return Value Type                           | Description                          |
151| ----------- | ------------------------------- | ------------------------------ |
152| setData(unifiedData: [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata))<sup>10+</sup>       | void   | Sets drag-related data in the drag event.|
153| getData()<sup>10+</sup> | [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata) | Obtains drag-related data from the drag event. For details about the data obtaining result, see the error code description.|
154| getSummary()<sup>10+</sup> | [Summary](../apis/js-apis-data-unifiedDataChannel.md#summary) | Obtains the summary of drag-related data from the drag event.|
155| setResult(dragRect: [DragResult](#dragresult10))<sup>10+</sup> | void | Sets the drag and drop result in the drag event.|
156| getResult()<sup>10+</sup> | [DragResult](#dragresult10) | Obtains the drag and drop result from the drag event.|
157| getPreviewRect()<sup>10+</sup> | [Rectangle](ts-universal-attributes-touch-target.md#rectangle) | Obtains the rectangle where the preview image is located.|
158| getVelocityX()<sup>10+</sup> | number | Obtains the dragging velocity along the x-axis. The origin of the coordinate axis is the upper left corner of the screen. The unit is vp. The velocity is positive if the movement is from left to right, and it is negative if the movement is from right to left.|
159| getVelocityY()<sup>10+</sup> | number | Obtains the dragging velocity along the y-axis. The origin of the coordinate axis is the upper left corner of the screen. The unit is vp. The velocity is positive if the movement is from top to bottom, and it is negative if the movement is from bottom to top.|
160| getVelocity()<sup>10+</sup> | number | Obtains the dragging velocity along the main axis. The value is the arithmetic square root of the sum of squares of the velocity along the x- and y-axis.|
161| getWindowX()<sup>10+</sup> | number | X coordinate of the drag position relative to the upper left corner of the window, in vp.|
162| getWindowY()<sup>10+</sup> | number | Y coordinate of the drag position relative to the upper left corner of the window, in vp.|
163| getDisplayX()<sup>10+</sup> | number | X coordinate of the drag position relative to the upper left corner of the screen, in vp.|
164| getDisplayY()<sup>10+</sup> | number | Y coordinate of the drag position relative to the upper left corner of the screen, in vp.|
165| getX()<sup>(deprecated)</sup> | number | X coordinate of the drag position relative to the upper left corner of the window, in vp.<br>This API is deprecated since API version 10. You are advised to use **getWindowX()** instead.|
166| getY()<sup>(deprecated)</sup> | number | Y coordinate of the drag position relative to the upper left corner of the window, in vp.<br>This API is deprecated since API version 10. You are advised to use **getWindowY()** instead.|
167
168
169**Error codes**
170
171For details about the error codes, see [Drag Event Error Codes](../errorcodes/errorcode-drag-event.md).
172
173| ID  | Error Message|
174| --------- | ------- |
175| 190001    | GetData failed, data not found. |
176| 190002    | GetData failed, data error. |
177
178## DragResult<sup>10+</sup>
179
180| Name| Description|
181| ----- | ----------------- |
182| DRAG_SUCCESSFUL | The drag and drop operation succeeded. It can be used in **onDrop**.|
183| DRAG_FAILED | The drag and drop operation failed. It can be used in **onDrop**.|
184| DRAG_CANCELED | The drag and drop operation was canceled. It can be used in **onDrop**.|
185| DROP_ENABLED | The component allows for a drop operation. It can be used in **onDragMove**.|
186| DROP_DISABLED | The component does not allow for a drop operation. It can be used in **onDragMove**.|
187
188## DragBehavior<sup>10+</sup>
189
190Provides the drag behavior. This API takes effect only when [DragResult](#dragresult10) is set to **DROP_ENABLED** and the [onDrop](#ondrop) callback is implemented.
191
192| Name| Description|
193| ----- | ----------------- |
194| COPY | Copy mode.|
195| MOVE| Paste mode.|
196
197
198## Example
199
200```ts
201// xxx.ets
202import UDC from '@ohos.data.unifiedDataChannel';
203import UTD from '@ohos.data.uniformTypeDescriptor';
204import promptAction from '@ohos.promptAction';
205import { BusinessError } from '@ohos.base';
206
207@Entry
208@Component
209struct Index {
210  @State targetImage: string = '';
211  @State targetText: string = 'Drag Text';
212  @State imageWidth: number = 100;
213  @State imageHeight: number = 100;
214  @State imgState: Visibility = Visibility.Visible;
215  @State videoSrc: string = 'resource://RAWFILE/02.mp4';
216  @State abstractContent: string = "abstract";
217  @State textContent: string = "";
218
219  @Builder
220  pixelMapBuilder() {
221    Column() {
222      Image($r('app.media.icon'))
223        .width(120)
224        .height(120)
225        .backgroundColor(Color.Yellow)
226    }
227  }
228
229  getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) {
230    try {
231      let data: UnifiedData = event.getData();
232      if (!data) {
233        return false;
234      }
235      let records: Array<UDC.UnifiedRecord> = data.getRecords();
236      if (!records || records.length <= 0) {
237        return false;
238      }
239      callback(event);
240      return true;
241    } catch (e) {
242      console.log("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message);
243      return false;
244    }
245  }
246
247  getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) {
248    if (this.getDataFromUdmfRetry(event, callback)) {
249      return;
250    }
251    setTimeout(() => {
252      this.getDataFromUdmfRetry(event, callback);
253    }, 1500);
254  }
255
256  build() {
257    Row() {
258      Column() {
259        Text('start Drag')
260          .fontSize(18)
261          .width('100%')
262          .height(40)
263          .margin(10)
264          .backgroundColor('#008888')
265        Image($r('app.media.icon'))
266          .width(100)
267          .height(100)
268          .draggable(true)
269          .margin({ left: 15 })
270          .visibility(this.imgState)
271          .onDragEnd((event) => {
272            // The result value obtained from onDragEnd is set in onDrop of the drop target.
273            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
274              promptAction.showToast({ duration: 100, message: 'Drag Success' });
275            } else if (event.getResult() === DragResult.DRAG_FAILED) {
276              promptAction.showToast({ duration: 100, message: 'Drag failed' });
277            }
278          })
279        Text('test drag event')
280          .width('100%')
281          .height(100)
282          .draggable(true)
283          .margin({ left: 15 })
284          .copyOption(CopyOptions.InApp)
285        TextArea({ placeholder: 'please input words' })
286          .copyOption(CopyOptions.InApp)
287          .width('100%')
288          .height(50)
289          .draggable(true)
290        Search({ placeholder: 'please input you word' })
291          .searchButton('Search')
292          .width('100%')
293          .height(80)
294          .textFont({ size: 20 })
295        Column() {
296          Text('change video source')
297        }.draggable(true)
298        .onDragStart((event) => {
299          let video: UDC.Video = new UDC.Video();
300          video.videoUri = '/resources/rawfile/01.mp4';
301          let data: UDC.UnifiedData = new UDC.UnifiedData(video);
302          (event as DragEvent).setData(data);
303          return { builder: () => {
304            this.pixelMapBuilder()
305          }, extraInfo: 'extra info' };
306        })
307
308        Column() {
309          Text('this is abstract')
310            .fontSize(20)
311            .width('100%')
312        }.margin({ left: 40, top: 20 })
313        .width('100%')
314        .height(100)
315        .onDragStart((event) => {
316          let data: UDC.PlainText = new UDC.PlainText();
317          data.abstract = 'this is abstract';
318          data.textContent = 'this is content this is content';
319          (event as DragEvent).setData(new UDC.UnifiedData(data));
320        })
321      }.width('45%')
322      .height('100%')
323
324      Column() {
325        Text('Drag Target Area')
326          .fontSize(20)
327          .width('100%')
328          .height(40)
329          .margin(10)
330          .backgroundColor('#008888')
331        Image(this.targetImage)
332          .width(this.imageWidth)
333          .height(this.imageHeight)
334          .draggable(true)
335          .margin({ left: 15 })
336          .border({ color: Color.Black, width: 1 })
337          .allowDrop([UTD.UniformDataType.IMAGE])
338          .onDrop((dragEvent?: DragEvent) => {
339            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
340              let records: Array<UDC.UnifiedRecord> = event.getData().getRecords();
341              let rect: Rectangle = event.getPreviewRect();
342              this.imageWidth = Number(rect.width);
343              this.imageHeight = Number(rect.height);
344              this.targetImage = (records[0] as UDC.Image).imageUri;
345              event.useCustomDropAnimation = false;
346              animateTo({ duration: 1000 }, () => {
347                this.imageWidth = 100;
348                this.imageHeight = 100;
349                this.imgState = Visibility.None;
350              })
351              // If result is explicitly set to successful, the value is passed in to onDragEnd of the drag source.
352              event.setResult(DragResult.DRAG_SUCCESSFUL);
353            })
354          })
355
356        Text(this.targetText)
357          .width('100%')
358          .height(100)
359          .border({ color: Color.Black, width: 1 })
360          .margin(15)
361          .allowDrop([UTD.UniformDataType.TEXT])
362          .onDrop((dragEvent?: DragEvent) => {
363            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
364              let records: Array<UDC.UnifiedRecord> = event.getData().getRecords();
365              let plainText: UDC.PlainText = records[0] as UDC.PlainText;
366              this.targetText = plainText.textContent;
367            })
368          })
369
370        Video({ src: this.videoSrc, previewUri: $r('app.media.icon') })
371          .width('100%')
372          .height(200)
373          .controls(true)
374          .allowDrop([UTD.UniformDataType.VIDEO])
375
376        Column() {
377          Text(this.abstractContent).fontSize(20).width('100%')
378          Text(this.textContent).fontSize(15).width('100%')
379        }
380        .width('100%')
381        .height(100)
382        .margin(20)
383        .border({ color: Color.Black, width: 1 })
384        .allowDrop([UTD.UniformDataType.PLAIN_TEXT])
385        .onDrop((dragEvent?: DragEvent) => {
386          this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
387            let records: Array<UDC.UnifiedRecord> = event.getData().getRecords();
388            let plainText: UDC.PlainText = records[0] as UDC.PlainText;
389            this.abstractContent = plainText.abstract as string;
390            this.textContent = plainText.textContent;
391          })
392        })
393      }.width('45%')
394      .height('100%')
395      .margin({ left: '5%' })
396    }
397    .height('100%')
398  }
399}
400```
401