• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 拖拽事件
2
3拖拽事件指组件被长按后拖拽时触发的事件。
4
5>  **说明:**
6>
7>  从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8>
9> 应用本身预置的资源文件(即应用在安装前的HAP包中已经存在的资源文件)仅支持本地应用内拖拽。
10
11ArkUI框架对以下组件实现了默认的拖拽能力,支持对数据的拖出或拖入响应,开发者只需要将这些组件的[draggale](ts-universal-attributes-drag-drop.md)属性设置为true,即可使用默认拖拽能力。
12
13- 默认支持拖出能力的组件(可从组件上拖出数据):Search、TextInput、TextArea、RichEditor、Text、Image、FormComponent、Hyperlink
14
15- 默认支持拖入能力的组件(目标组件可响应拖入数据):Search、TextInput、TextArea、Video
16
17开发者也可以通过实现通用拖拽事件来自定义拖拽响应。
18
19其他组件需要开发者将draggable属性设置为true,并在onDragStart等接口中实现数据传输相关内容,才能正确处理拖拽。
20
21## 事件
22
23| 名称                                                         | 支持冒泡 | 功能描述                                                     |
24| ------------------------------------------------------------ | -------- | ------------------------------------------------------------ |
25| onDragStart(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;&nbsp;[CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo说明)) | 否       | 第一次拖拽此事件绑定的组件时,长按时间 >= 500ms,然后手指移动距离 >= 10vp,触发回调。<br/>- event:拖拽事件信息,详见[DragEvent](#dragevent说明)。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/> 返回值:拖拽过程中显示的组件信息。<br/>触发条件:长按时间 >= 500ms。<br> 事件优先级:长按触发时间 < 500ms,长按事件优先拖拽事件响应,长按触发时间 >= 500ms,拖拽事件优先长按事件响应。 |
26| onDragEnter(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 拖拽进入组件范围内时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 |
27| onDragMove(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 拖拽在组件范围内移动时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 |
28| onDragLeave(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 拖拽离开组件范围内时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 |
29| onDrop(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void) | 否       | 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。 |
30| onDragEnd(event:&nbsp;(event?:&nbsp;[DragEvent](#dragevent说明),&nbsp;extraParams?:&nbsp;string)&nbsp;=&gt;&nbsp;void)<sup>10+</sup> | 否       | 绑定此事件的组件触发的拖拽结束后,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。 |
31
32## DragItemInfo说明
33
34| 名称      | 类型                                     | 必填   | 描述                                |
35| --------- | ---------------------------------------- | ---- | --------------------------------- |
36| pixelMap  | [PixelMap](../apis/js-apis-image.md#pixelmap7) | 否    | 设置拖拽过程中显示的图片。                     |
37| builder   | [CustomBuilder](ts-types.md#custombuilder8) | 否    | 拖拽过程中显示自定义组件,如果设置了pixelMap,则忽略此值。<br/> **说明:** <br/>不支持全局builder。如果builder中使用了[Image](../arkui-ts/ts-basic-components-image.md)组件,应尽量开启同步加载,即配置Image的[syncLoad](../arkui-ts/ts-basic-components-image.md#属性)为true。该builder只用于生成当次拖拽中显示的图片,builder的修改不会同步到当前正在拖拽的图片,对builder的修改需要在下一次拖拽时生效。 |
38| extraInfo | string                                   | 否    | 拖拽项的描述。                           |
39
40
41## extraParams说明
42
43  用于返回组件在拖拽中需要用到的额外信息。
44
45  extraParams是Json对象转换的string字符串,可以通过Json.parse转换的Json对象获取如下属性。
46
47| 名称          | 类型   | 描述                                       |
48| ------------- | ------ | ---------------------------------------- |
49| selectedIndex | number | 当拖拽事件设在父容器的子元素时,selectedIndex表示当前被拖拽子元素是父容器第selectedIndex个子元素,selectedIndex从0开始。<br/>仅在ListItem组件的拖拽事件中生效。 |
50| insertIndex   | number | 当前拖拽元素在List组件中放下时,insertIndex表示被拖拽元素插入该组件的第insertIndex个位置,insertIndex从0开始。<br/>仅在List组件的拖拽事件中生效。 |
51
52## DragEvent说明
53
54### 属性
55
56| 名称     | 类型  | 描述             |
57| ------ | ------ | ---------------- |
58| useCustomDropAnimation<sup>10+</sup> | boolean | 当拖拽结束时,是否使能并使用系统默认落位动效。<br/>应用可将该值设定为true来禁用系统默认落位动效,并实现自己的自定义动效。<br/>当不配置或设置为false时,系统默认落位动效生效,此情况下,应用不应再实现自定义动效,以避免动效上的冲突。|
59|dragBehavior<sup>10+</sup> | [DragBehavior](#dragbehavior10) | 切换复制和剪贴模式的角标显示状态。 |
60
61### 方法
62
63| 名称     | 返回值类型                            | 描述                           |
64| ----------- | ------------------------------- | ------------------------------ |
65| setData(unifiedData: [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata))<sup>10+</sup>       | void   | 向DragEvent中设置拖拽相关数据。 |
66| getData()<sup>10+</sup> | [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata) | 从DragEvent中获取拖拽相关数据。数据获取结果请参考错误码说明。 |
67| getSummary()<sup>10+</sup> | [Summary](../apis/js-apis-data-unifiedDataChannel.md#summary) | 从DragEvent中获取拖拽相关数据的简介。 |
68| setResult(dragRect: [DragResult](#dragresult10枚举说明))<sup>10+</sup> | void | 向DragEvent中设置拖拽结果。 |
69| getResult()<sup>10+</sup> | [DragResult](#dragresult10枚举说明) | 从DragEvent中获取拖拽结果。 |
70| getPreviewRect()<sup>10+</sup> | [Rectangle](ts-universal-attributes-touch-target.md#rectangle对象说明) | 获取预览图所在的Rectangle。 |
71| getVelocityX()<sup>10+</sup> | number | 获取当前拖拽的x轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从左往右为正,反之为负。 |
72| getVelocityY()<sup>10+</sup> | number | 获取当前拖拽的y轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从上往下为正,反之为负。 |
73| getVelocity()<sup>10+</sup> | number | 获取当前拖拽的主方向拖动速度。为xy轴方向速度的平方和的算术平方根。 |
74| getWindowX()<sup>10+</sup> | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。 |
75| getWindowY()<sup>10+</sup> | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。 |
76| getDisplayX()<sup>10+</sup> | number | 当前拖拽点相对于屏幕左上角的x轴坐标,单位为vp。 |
77| getDisplayY()<sup>10+</sup> | number | 当前拖拽点相对于屏幕左上角的y轴坐标,单位为vp。 |
78| getX()<sup>(deprecated)</sup> | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。<br>从API verdion 10开始不再维护,建议使用getWindowX()代替。 |
79| getY()<sup>(deprecated)</sup> | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。<br>从API verdion 10开始不再维护,建议使用getWindowY()代替。 |
80
81
82**错误码:**
83
84以下错误码的详细介绍请参见[drag-event(拖拽事件)](../errorcodes/errorcode-drag-event.md)错误码。
85
86| 错误码ID   | 错误信息 |
87| --------- | ------- |
88| 190001    | GetData failed, data not found. |
89| 190002    | GetData failed, data error. |
90
91## DragResult<sup>10+</sup>枚举说明
92
93| 名称 | 描述 |
94| ----- | ----------------- |
95| DRAG_SUCCESSFUL | 拖拽成功 |
96| DRAG_FAILED | 拖拽失败 |
97| DRAG_CANCELED | 拖拽取消 |
98| DROP_ENABLED | 组件允许落入 |
99| DROP_DISABLED | 组件不允许落入 |
100
101## DragBehavior<sup>10+</sup>
102
103需要设置[DragResult](#dragresult10枚举说明)为DROP_ENABLED,并实现[onDrop](#事件)回调时才能够生效。
104
105| 名称 | 描述 |
106| ----- | ----------------- |
107| COPY | 复制模式角标。 |
108| MOVE| 剪贴模式角标。 |
109
110
111## 示例
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