• 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 actions by default: **\<Search>**, **\<TextInput>**, **\<TextArea>**, **\<RichEditor>**, **\<Text>**, **\<Image>**, **\<FormComponent>**, **\<Hyperlink>**
14
15- The following component supports drop actions 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
22## Events
23
24| Name                                                        | Bubbling Supported| Description                                                    |
25| ------------------------------------------------------------ | -------- | ------------------------------------------------------------ |
26| onDragStart(event: (event?: [DragEvent](#dragevent), extraParams?: string) =&gt;  [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo)) | No      | Triggered when the component bound to the event is dragged for the first time.<br>- **event**: information about the drag event. For details, see [DragEvent](#dragevent).<br>- **extraParams**: additional information about the drag event. For details, see **[extraParams](#extraparams)**.<br> Return value: component information displayed during dragging.<br>Trigger condition: long press for at least 500 ms.<br> Event priority:<br>- Long press time < 500 ms: Long press event > Drag event<br> - Other: Drag event > Long press event|
27| onDragEnter(event: (event?: [DragEvent](#dragevent), extraParams?: string) =&gt; void) | No      | Triggered when the dragged item enters a valid drop target.<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. For details, see **[extraParams](#extraparams)**.<br>This event is valid only when a listener for the **onDrop** event is enabled.|
28| onDragMove(event: (event?: [DragEvent](#dragevent), extraParams?: string) =&gt; void) | No      | Triggered when the dragged item moves in a valid drop target.<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. For details, see **[extraParams](#extraparams)**.<br>This event is valid only when a listener for the **onDrop** event is enabled.|
29| onDragLeave(event: (event?: [DragEvent](#dragevent), extraParams?: string) =&gt; void) | No      | Triggered when the dragged item leaves a valid drop target.<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. For details, see **[extraParams](#extraparams)**.<br>This event is valid only when a listener for the **onDrop** event is enabled.|
30| onDrop(event: (event?: [DragEvent](#dragevent), extraParams?: string) =&gt; void) | No      | Triggered when the dragged item is dropped on a valid drop target.<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. For details, see **[extraParams](#extraparams)**.|
31| onDragEnd(event: (event?: [DragEvent](#dragevent), extraParams?: string) =&gt; void)<sup>10+</sup> | No      | Triggered when the dragging of the component bound to the event ends.<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. For details, see **[extraParams](#extraparams)**.|
32
33## DragItemInfo
34
35| Name     | Type                                    | Mandatory  | Description                               |
36| --------- | ---------------------------------------- | ---- | --------------------------------- |
37| pixelMap  | [PixelMap](../apis/js-apis-image.md#pixelmap7) | No   | Image to be displayed during dragging.                    |
38| 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 whenever possible, that is, set the [syncLoad](../arkui-ts/ts-basic-components-image.md#attributes) 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.|
39| extraInfo | string                                   | No   | Extra information of the dragged item.                          |
40
41
42## extraParams
43
44  Provides additional information required for dragging an item.
45
46  **extraParams** is a string converted from a JSON object. You can obtain the following attributes using the JSON object converted from **Json.parse**.
47
48| Name         | Type  | Description                                      |
49| ------------- | ------ | ---------------------------------------- |
50| 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.|
51| 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.|
52
53## DragEvent
54
55### Attributes
56
57| Name    | Type | Description            |
58| ------ | ------ | ---------------- |
59| 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.|
60|dragBehavior<sup>10+</sup> | [DragBehavior](#dragbehavior10) | Copy or paste mode.|
61
62### Methods
63
64| Name    | Return Value Type                           | Description                          |
65| ----------- | ------------------------------- | ------------------------------ |
66| setData(unifiedData: [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata))<sup>10+</sup>       | void   | Sets drag-related data in the drag event.|
67| 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.|
68| getSummary()<sup>10+</sup> | [Summary](../apis/js-apis-data-unifiedDataChannel.md#summary) | Obtains the summary of drag-related data from the drag event.|
69| setResult(dragRect: [DragResult](#dragresult10))<sup>10+</sup> | void | Sets the drag and drop result in the drag event.|
70| getResult()<sup>10+</sup> | [DragResult](#dragresult10) | Obtains the drag and drop result from the drag event.|
71| getPreviewRect()<sup>10+</sup> | [Rectangle](ts-universal-attributes-touch-target.md#rectangle) | Obtains the rectangle where the preview image is located.|
72| 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.|
73| 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.|
74| 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.|
75| getWindowX()<sup>10+</sup> | number | X coordinate of the drag position relative to the upper left corner of the window, in vp.|
76| getWindowY()<sup>10+</sup> | number | Y coordinate of the drag position relative to the upper left corner of the window, in vp.|
77| getDisplayX()<sup>10+</sup> | number | X coordinate of the drag position relative to the upper left corner of the screen, in vp.|
78| getDisplayY()<sup>10+</sup> | number | Y coordinate of the drag position relative to the upper left corner of the screen, in vp.|
79| 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.|
80| 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.|
81
82**Error codes**
83
84For details about the error codes, see [Drag Event Error Codes](../errorcodes/errorcode-drag-event.md).
85
86| ID  | Error Message|
87| --------- | ------- |
88| 190001    | GetData failed, data not found. |
89| 190002    | GetData failed, data error. |
90
91## DragResult<sup>10+</sup>
92
93| Name| Description|
94| ----- | ----------------- |
95| DRAG_SUCCESSFUL | The drag and drop operation succeeded.|
96| DRAG_FAILED | The drag and drop operation failed.|
97| DRAG_CANCELED | The drag and drop operation was canceled.|
98| DROP_ENABLED | The component allows for a drop operation.|
99| DROP_DISABLED | The component does not allow for a drop operation.|
100
101## DragBehavior<sup>10+</sup>
102
103Provides the drag behavior. This API takes effect only when [DragResult](#dragresult10) is set to **DROP_ENABLED** and the [onDrop](#events) callback is implemented.
104
105| Name| Description|
106| ----- | ----------------- |
107| COPY | Copy mode.|
108| MOVE| Paste mode.|
109
110
111## Example
112
113```ts
114// xxx.ets
115import UDC from '@ohos.data.unifiedDataChannel';
116import UTD from '@ohos.data.uniformTypeDescriptor';
117import promptAction from '@ohos.promptAction';
118import { BusinessError } from '@ohos.base';
119
120@Entry
121@Component
122struct Index {
123  @State targetImage: string = '';
124  @State targetText: string = 'Drag Text';
125  @State imageWidth: number = 100;
126  @State imageHeight: number = 100;
127  @State imgState: Visibility = Visibility.Visible;
128  @State videoSrc: string = 'resource://RAWFILE/02.mp4';
129  @State abstractContent: string = "abstract";
130  @State textContent: string = "";
131
132  getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent)=>void)
133  {
134    try {
135      let data:UnifiedData = event.getData();
136      if (!data) {
137        return false;
138      }
139      let records: Array<UDC.UnifiedRecord> = data.getRecords();
140      if (!records || records.length <= 0) {
141        return false;
142      }
143      callback(event);
144      return true;
145    } catch (e) {
146      console.log("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message);
147      return false;
148    }
149  }
150
151  getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) {
152    if (this.getDataFromUdmfRetry(event, callback)) {
153      return;
154    }
155    setTimeout(() => {
156      this.getDataFromUdmfRetry(event, callback);
157    }, 1500);
158  }
159
160  build() {
161    Row() {
162      Column() {
163        Text('start Drag')
164          .fontSize(18)
165          .width('100%')
166          .height(40)
167          .margin(10)
168          .backgroundColor('#008888')
169        Image($r('app.media.icon'))
170          .width(100)
171          .height(100)
172          .draggable(true)
173          .margin({left: 15})
174          .visibility(this.imgState)
175          .onDragEnd((event)=>{
176            if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
177              promptAction.showToast({duration: 100, message: 'Drag Success'});
178            } else if (event.getResult() === DragResult.DRAG_FAILED) {
179              promptAction.showToast({duration: 100, message: 'Drag failed'});
180            }
181          })
182        Text('test drag event')
183          .width('100%')
184          .height(100)
185          .draggable(true)
186          .margin({left: 15})
187          .copyOption(CopyOptions.InApp)
188        TextArea({placeholder: 'please input words'})
189          .copyOption(CopyOptions.InApp)
190          .width('100%')
191          .height(50)
192          .draggable(true)
193        Search({placeholder: 'please input you word'})
194          .searchButton('Search')
195          .width('100%')
196          .height(80)
197          .textFont({size: 20})
198        Column() {
199          Text('change video source')
200        }.draggable(true)
201        .onDragStart((event)=>{
202          let video: UDC.Video = new UDC.Video();
203          video.videoUri = '/resources/rawfile/01.mp4';
204          let data: UDC.UnifiedData = new UDC.UnifiedData(video);
205          (event as DragEvent).setData(data);
206        })
207        Column() {
208          Text('this is abstract')
209            .fontSize(20)
210            .width('100%')
211        }.margin({left: 40, top: 20})
212        .width('100%')
213        .height(100)
214        .onDragStart((event)=>{
215          let data: UDC.PlainText = new UDC.PlainText();
216          data.abstract = 'this is abstract';
217          data.textContent = 'this is content this is content';
218          (event as DragEvent).setData(new UDC.UnifiedData(data));
219        })
220      }.width('45%')
221      .height('100%')
222
223      Column() {
224        Text('Drag Target Area')
225          .fontSize(20)
226          .width('100%')
227          .height(40)
228          .margin(10)
229          .backgroundColor('#008888')
230        Image(this.targetImage)
231          .width(this.imageWidth)
232          .height(this.imageHeight)
233          .draggable(true)
234          .margin({ left: 15 })
235          .border({ color: Color.Black, width: 1 })
236          .allowDrop([UTD.UniformDataType.IMAGE])
237          .onDrop((dragEvent?: DragEvent) => {
238            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
239              let records: Array<UDC.UnifiedRecord> = event.getData().getRecords();
240              let rect: Rectangle = event.getPreviewRect();
241              this.imageWidth = Number(rect.width);
242              this.imageHeight = Number(rect.height);
243              this.targetImage = (records[0] as UDC.Image).imageUri;
244              event.useCustomDropAnimation = false;
245              animateTo({ duration: 1000 }, () => {
246                this.imageWidth = 100;
247                this.imageHeight = 100;
248                this.imgState = Visibility.None;
249              })
250              event.setResult(DragResult.DRAG_SUCCESSFUL);
251            })
252          })
253
254        Text(this.targetText)
255          .width('100%')
256          .height(100)
257          .border({ color: Color.Black, width: 1 })
258          .margin(15)
259          .allowDrop([UTD.UniformDataType.TEXT])
260          .onDrop((dragEvent?: DragEvent) => {
261            this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
262              let records: Array<UDC.UnifiedRecord> = event.getData().getRecords();
263              let plainText: UDC.PlainText = records[0] as UDC.PlainText;
264              this.targetText = plainText.textContent;
265            })
266          })
267
268        Video({ src: this.videoSrc, previewUri: $r('app.media.icon') })
269          .width('100%')
270          .height(200)
271          .controls(true)
272          .allowDrop([UTD.UniformDataType.VIDEO])
273
274        Column() {
275          Text(this.abstractContent).fontSize(20).width('100%')
276          Text(this.textContent).fontSize(15).width('100%')
277        }
278        .width('100%')
279        .height(100)
280        .margin(20)
281        .border({ color: Color.Black, width: 1 })
282        .allowDrop([UTD.UniformDataType.PLAIN_TEXT])
283        .onDrop((dragEvent?: DragEvent) => {
284          this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
285            let records: Array<UDC.UnifiedRecord> = event.getData().getRecords();
286            let plainText: UDC.PlainText = records[0] as UDC.PlainText;
287            this.abstractContent = plainText.abstract as string;
288            this.textContent = plainText.textContent;
289          })
290        })
291      }.width('45%')
292      .height('100%')
293      .margin({ left: '5%' })
294    }
295    .height('100%')
296  }
297}
298```
299