# 拖拽事件 拖拽事件指组件被长按后拖拽时触发的事件。 > **说明:** > > 从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 > > 应用本身预置的资源文件(即应用在安装前的HAP包中已经存在的资源文件)仅支持本地应用内拖拽。 ArkUI组件默认不支持拖拽。 当以下组件的[draggable](ts-universal-attributes-drag-drop.md)属性设置为true时可以响应拖拽事件,此时,组件不需要配置数据传输,即可进行拖拽。其他组件需要开发者将[draggable](ts-universal-attributes-drag-drop.md)属性设置为true且在onDragStart等接口中实现数据传输相关内容,才能完成拖拽。 - 默认支持拖拽(拖入和拖出)的组件:Search、TextInput、TextArea - 默认支持拖入的组件:Video - 默认支持拖出的组件:Text、List、Grid、FormComponent、Image、Hyperlink ## 事件 | 名称 | 支持冒泡 | 功能描述 | | ------------------------------------------------------------ | -------- | ------------------------------------------------------------ | | onDragStart(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) =>  [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo说明)) | 否 | 第一次拖拽此事件绑定的组件时,触发回调。
- event:拖拽事件信息,详见[DragEvent](#dragevent说明)。
- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。
返回值:拖拽过程中显示的组件信息。
触发条件:长按时间 >= 500ms。
事件优先级:长按触发时间 < 500ms,长按事件 > 拖拽事件
其他: 拖拽事件 > 长按事件。
**说明:**
当前不支持同时配置[dragController.executeDrag](../apis/js-apis-arkui-dragController.md#dragcontrollerexecutedrag)和onDragStart。| | onDragEnter(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 拖拽进入组件范围内时,触发回调。
- event:拖拽事件信息,包括拖拽点坐标。
- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。
当监听了onDrop事件时,此事件才有效。 | | onDragMove(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 拖拽在组件范围内移动时,触发回调。
- event:拖拽事件信息,包括拖拽点坐标。
- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。
当监听了onDrop事件时,此事件才有效。 | | onDragLeave(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 拖拽离开组件范围内时,触发回调。
- event:拖拽事件信息,包括拖拽点坐标。
- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。
当监听了onDrop事件时,此事件才有效。 | | onDrop(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。
- event:拖拽事件信息,包括拖拽点坐标。
- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。 | | onDragEnd(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void)10+ | 否 | 绑定此事件的组件触发的拖拽结束后,触发回调。
- event:拖拽事件信息,包括拖拽点坐标。
- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。 | ## DragItemInfo说明 | 名称 | 类型 | 必填 | 描述 | | --------- | ---------------------------------------- | ---- | --------------------------------- | | pixelMap | [PixelMap](../apis/js-apis-image.md#pixelmap7) | 否 | 设置拖拽过程中显示的图片。 | | builder | [CustomBuilder](ts-types.md#custombuilder8) | 否 | 拖拽过程中显示自定义组件,如果设置了pixelMap,则忽略此值。 | | extraInfo | string | 否 | 拖拽项的描述。 | ## extraParams说明 用于返回组件在拖拽中需要用到的额外信息。 extraParams是Json对象转换的string字符串,可以通过Json.parse转换的Json对象获取如下属性。 | 名称 | 类型 | 描述 | | ------------- | ------ | ---------------------------------------- | | selectedIndex | number | 当拖拽事件设在父容器的子元素时,selectedIndex表示当前被拖拽子元素是父容器第selectedIndex个子元素,selectedIndex从0开始。
仅在ListItem组件的拖拽事件中生效。 | | insertIndex | number | 当前拖拽元素在List组件中放下时,insertIndex表示被拖拽元素插入该组件的第insertIndex个位置,insertIndex从0开始。
仅在List组件的拖拽事件中生效。 | ## DragEvent说明 | 名称 | 类型 | 描述 | | ------ | ------ | ---------------- | | useCustomDropAnimation10+ | boolean | 当拖拽结束时,是否使用系统默认落入动画。 | | setData(unifiedData: [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata))10+ | void | 向DragEvent中设置拖拽相关数据。 | | getData()10+ | [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata) | 从DragEvent中获取拖拽相关数据。数据获取结果请参考错误码说明。 | | getSummary()10+ | [Summary](../apis/js-apis-data-unifiedDataChannel.md#summary) | 从DragEvent中获取拖拽相关数据的简介。 | | setResult(dragRect: [DragResult](#dragresult10枚举说明))10+ | void | 向DragEvent中设置拖拽结果。 | | getResult()10+ | [DragResult](#dragresult10枚举说明) | 从DragEvent中获取拖拽结果。 | | getPreviewRect()10+ | [Rectangle](ts-universal-attributes-touch-target.md#rectangle对象说明) | 获取预览图所在的Rectangle。 | | getVelocityX()10+ | number | 获取当前拖拽的x轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从左往右为正,反之为负。 | | getVelocityY()10+ | number | 获取当前拖拽的y轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从上往下为正,反之为负。 | | getVelocity()10+ | number | 获取当前拖拽的主方向拖动速度。为xy轴方向速度的平方和的算术平方根。 | | getWindowX()10+ | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。 | | getWindowY()10+ | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。 | | getDisplayX()10+ | number | 当前拖拽点相对于屏幕左上角的x轴坐标,单位为vp。 | | getDisplayY()10+ | number | 当前拖拽点相对于屏幕左上角的y轴坐标,单位为vp。 | | getX()(deprecated) | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。
从API verdion 10开始不再维护,建议使用getWindowX()代替。 | | getY()(deprecated) | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。
从API verdion 10开始不再维护,建议使用getWindowY()代替。 | **错误码:** 以下错误码的详细介绍请参见[drag-event(拖拽事件)](../errorcodes/errorcode-drag-event.md)错误码。 | 错误码ID | 错误信息 | | --------- | ------- | | 190001 | GetData failed, data not found. | | 190002 | GetData failed, data error. | ## DragResult10+枚举说明 | 名称 | 描述 | | ----- | ----------------- | | DRAG_SUCCESSFUL | 拖拽成功 | | DRAG_FAILED | 拖拽失败 | | DRAG_CANCELED | 拖拽取消 | | DROP_ENABLED | 组件允许落入 | | DROP_DISABLED | 组件不允许落入 | ## 示例 ```ts import UDC from '@ohos.data.unifiedDataChannel'; import UTD from '@ohos.data.uniformTypeDescriptor'; import promptAction from '@ohos.promptAction'; @Entry @Component struct Index { @State targetImage: string = ''; @State targetText: string = 'Drag Text'; @State imageWidth: number = 100; @State imageHeight: number = 100; @State imgState: Visibility = Visibility.Visible; @State videoSrc: string = 'resource://RAWFILE/02.mp4'; @State abstractContent: string = "abstract"; @State textContent: string = ""; getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent)=>void) { try { let data = event.getData(); if (!data) { return false; } let records: Array = data.getRecords(); if (!records || records.length <= 0) { return false; } callback(event); return true; } catch (e) { console.log("getData failed, code = " + e.code + ", message = " + e.message); return false; } } getDataFromUdmf(event: DragEvent, callback: (data: DragEvent)=>void) { if(this.getDataFromUdmfRetry(event, callback)) { return; } setTimeout(()=>{ this.getDataFromUdmfRetry(event, callback); }, 1500); } build() { Row() { Column() { Text('start Drag') .fontSize(18) .width('100%') .height(40) .margin(10) .backgroundColor('#008888') Image($r('app.media.icon')) .width(100) .height(100) .draggable(true) .margin({left: 15}) .visibility(this.imgState) .onDragEnd((event)=>{ if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { promptAction.showToast({duration: 100, message: 'Drag Success'}); } else if (event.getResult() === DragResult.DRAG_FAILED) { promptAction.showToast({duration: 100, message: 'Drag failed'}); } }) Text('test drag event') .width('100%') .height(100) .draggable(true) .margin({left: 15}) .copyOption(CopyOptions.InApp) TextArea({placeholder: 'please input words'}) .copyOption(CopyOptions.InApp) .width('100%') .height(50) .draggable(true) Search({placeholder: 'please input you word'}) .searchButton('Search') .width('100%') .height(80) .textFont({size: 20}) Column() { Text('change video source') }.draggable(true) .onDragStart((event)=>{ let video: UDC.Video = new UDC.Video(); video.videoUri = 'resource://RAWFILE/01.mp4'; let data: UDC.UnifiedData = new UDC.UnifiedData(video); event.setData(data); }) Column() { Text('this is abstract') .fontSize(20) .width('100%') }.margin({left: 40, top: 20}) .width('100%') .height(100) .onDragStart((event)=>{ let data: UDC.PlainText = new UDC.PlainText(); data.abstract = 'this is abstract'; data.textContent = 'this is content this is content'; event.setData(new UDC.UnifiedData(data)); }) }.width('45%') .height('100%') Column() { Text('Drag Target Area') .fontSize(20) .width('100%') .height(40) .margin(10) .backgroundColor('#008888') Image(this.targetImage) .width(this.imageWidth) .height(this.imageHeight) .draggable(true) .margin({left: 15}) .border({color: Color.Black, width: 1}) .allowDrop([UTD.UniformDataType.IMAGE]) .onDrop((dragEvent: DragEvent)=> { this.getDataFromUdmf(dragEvent, (event)=>{ let records: Array = event.getData().getRecords(); let rect: Rectangle = event.getPreviewRect(); this.imageWidth = Number(rect.width); this.imageHeight = Number(rect.height); this.targetImage = ((records[0])).imageUri; event.useCustomDropAnimation = false; animateTo({duration: 1000}, ()=>{ this.imageWidth = 100; this.imageHeight = 100; this.imgState = Visibility.None; }) event.setResult(DragResult.DRAG_SUCCESSFUL); }) }) Text(this.targetText) .width('100%') .height(100) .border({color: Color.Black, width: 1}) .margin(15) .allowDrop([UTD.UniformDataType.TEXT]) .onDrop((dragEvent: DragEvent)=>{ this.getDataFromUdmf(dragEvent, event => { let records:Array = event.getData().getRecords(); this.targetText = ((records[0])).details['value']; }) }) Video({src: this.videoSrc, previewUri: $r('app.media.icon')}) .width('100%') .height(200) .controls(true) .allowDrop([UTD.UniformDataType.VIDEO]) Column() { Text(this.abstractContent).fontSize(20).width('100%') Text(this.textContent).fontSize(15).width('100%') }.width('100%').height(100).margin(20).border({color: Color.Black, width: 1}) .allowDrop([UTD.UniformDataType.PLAIN_TEXT]) .onDrop((dragEvent)=>{ this.getDataFromUdmf(dragEvent, event=>{ let records: Array = event.getData().getRecords(); let plainText: UDC.PlainText = (records[0]); this.abstractContent = plainText.abstract; this.textContent = plainText.textContent; }) }) }.width('45%') .height('100%') .margin({left: '5%'}) } .height('100%') } } ```