1# 拖拽事件 2 3拖拽事件指组件被长按后拖拽时触发的事件。 4 5> **说明:** 6> 7> 从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 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: (event?: [DragEvent](#dragevent说明), extraParams?: string) => [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](#dragiteminfo说明)) | 否 | 第一次拖拽此事件绑定的组件时,触发回调。<br/>- event:拖拽事件信息,详见[DragEvent](#dragevent说明)。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/> 返回值:拖拽过程中显示的组件信息。<br/>触发条件:长按时间 >= 500ms。<br> 事件优先级:长按触发时间 < 500ms,长按事件 > 拖拽事件<br> 其他: 拖拽事件 > 长按事件。 | 26| onDragEnter(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 拖拽进入组件范围内时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 | 27| onDragMove(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 拖拽在组件范围内移动时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 | 28| onDragLeave(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 拖拽离开组件范围内时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。<br/>当监听了onDrop事件时,此事件才有效。 | 29| onDrop(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => void) | 否 | 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。<br/>- event:拖拽事件信息,包括拖拽点坐标。<br/>- extraParams:拖拽事件额外信息,详见[extraParams](#extraparams说明)说明。 | 30| onDragEnd(event: (event?: [DragEvent](#dragevent说明), extraParams?: string) => 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,则忽略此值。 | 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| useCustomDropAnimation<sup>10+</sup> | boolean | 当拖拽结束时,是否使用系统默认落入动画。 | 57| setData(unifiedData: [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata))<sup>10+</sup> | void | 向DragEvent中设置拖拽相关数据。 | 58| getData()<sup>10+</sup> | [UnifiedData](../apis/js-apis-data-unifiedDataChannel.md#unifieddata) | 从DragEvent中获取拖拽相关数据。数据获取结果请参考错误码说明。 | 59| getSummary()<sup>10+</sup> | [Summary](../apis/js-apis-data-unifiedDataChannel.md#summary) | 从DragEvent中获取拖拽相关数据的简介。 | 60| setResult(dragRect: [DragResult](#dragresult10枚举说明))<sup>10+</sup> | void | 向DragEvent中设置拖拽结果。 | 61| getResult()<sup>10+</sup> | [DragResult](#dragresult10枚举说明) | 从DragEvent中获取拖拽结果。 | 62| getPreviewRect()<sup>10+</sup> | [Rectangle](ts-universal-attributes-touch-target.md#rectangle对象说明) | 获取预览图所在的Rectangle。 | 63| getVelocityX()<sup>10+</sup> | number | 获取当前拖拽的x轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从左往右为正,反之为负。 | 64| getVelocityY()<sup>10+</sup> | number | 获取当前拖拽的y轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从上往下为正,反之为负。 | 65| getVelocity()<sup>10+</sup> | number | 获取当前拖拽的主方向拖动速度。为xy轴方向速度的平方和的算术平方根。 | 66| getWindowX()<sup>10+</sup> | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。 | 67| getWindowY()<sup>10+</sup> | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。 | 68| getDisplayX()<sup>10+</sup> | number | 当前拖拽点相对于屏幕左上角的x轴坐标,单位为vp。 | 69| getDisplayY()<sup>10+</sup> | number | 当前拖拽点相对于屏幕左上角的y轴坐标,单位为vp。 | 70| getX()<sup>(deprecated)</sup> | number | 当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。<br>从API verdion 10开始不再维护,建议使用getWindowX()代替。 | 71| getY()<sup>(deprecated)</sup> | number | 当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。<br>从API verdion 10开始不再维护,建议使用getWindowY()代替。 | 72 73**错误码:** 74 75以下错误码的详细介绍请参见[drag-event(拖拽事件)](../errorcodes/errorcode-drag-event.md)错误码。 76 77| 错误码ID | 错误信息 | 78| --------- | ------- | 79| 190001 | GetData failed, data not found. | 80| 190002 | GetData failed, data error. | 81 82## DragResult<sup>10+</sup>枚举说明 83 84| 名称 | 描述 | 85| ----- | ----------------- | 86| DRAG_SUCCESSFUL | 拖拽成功 | 87| DRAG_FAILED | 拖拽失败 | 88| DRAG_CANCELED | 拖拽取消 | 89| DROP_ENABLED | 组件允许落入 | 90| DROP_DISABLED | 组件不允许落入 | 91 92## 示例 93 94```ts 95import UDC from '@ohos.data.unifiedDataChannel'; 96import UTD from '@ohos.data.uniformTypeDescriptor'; 97import promptAction from '@ohos.promptAction'; 98import { BusinessError } from '@ohos.base'; 99 100@Entry 101@Component 102struct Index { 103 @State targetImage: string = ''; 104 @State targetText: string = 'Drag Text'; 105 @State imageWidth: number = 100; 106 @State imageHeight: number = 100; 107 @State imgState: Visibility = Visibility.Visible; 108 @State videoSrc: string = 'resource://RAWFILE/02.mp4'; 109 @State abstractContent: string = "abstract"; 110 @State textContent: string = ""; 111 112 getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent)=>void) 113 { 114 try { 115 let data:UnifiedData = event.getData(); 116 if (!data) { 117 return false; 118 } 119 let records: Array<UDC.UnifiedRecord> = data.getRecords(); 120 if (!records || records.length <= 0) { 121 return false; 122 } 123 callback(event); 124 return true; 125 } catch (e) { 126 console.log("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message); 127 return false; 128 } 129 } 130 131 getDataFromUdmf(event: DragEvent, callback: (data: DragEvent)=>void) 132 { 133 if(this.getDataFromUdmfRetry(event, callback)) { 134 return; 135 } 136 setTimeout(()=>{ 137 this.getDataFromUdmfRetry(event, callback); 138 }, 1500); 139 } 140 141 build() { 142 Row() { 143 Column() { 144 Text('start Drag') 145 .fontSize(18) 146 .width('100%') 147 .height(40) 148 .margin(10) 149 .backgroundColor('#008888') 150 Image($r('app.media.icon')) 151 .width(100) 152 .height(100) 153 .draggable(true) 154 .margin({left: 15}) 155 .visibility(this.imgState) 156 .onDragEnd((event)=>{ 157 if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { 158 promptAction.showToast({duration: 100, message: 'Drag Success'}); 159 } else if (event.getResult() === DragResult.DRAG_FAILED) { 160 promptAction.showToast({duration: 100, message: 'Drag failed'}); 161 } 162 }) 163 Text('test drag event') 164 .width('100%') 165 .height(100) 166 .draggable(true) 167 .margin({left: 15}) 168 .copyOption(CopyOptions.InApp) 169 TextArea({placeholder: 'please input words'}) 170 .copyOption(CopyOptions.InApp) 171 .width('100%') 172 .height(50) 173 .draggable(true) 174 Search({placeholder: 'please input you word'}) 175 .searchButton('Search') 176 .width('100%') 177 .height(80) 178 .textFont({size: 20}) 179 Column() { 180 Text('change video source') 181 }.draggable(true) 182 .onDragStart((event)=>{ 183 let video: UDC.Video = new UDC.Video(); 184 video.videoUri = '/resources/rawfile/01.mp4'; 185 let data: UDC.UnifiedData = new UDC.UnifiedData(video); 186 (event as DragEvent).setData(data); 187 }) 188 Column() { 189 Text('this is abstract') 190 .fontSize(20) 191 .width('100%') 192 }.margin({left: 40, top: 20}) 193 .width('100%') 194 .height(100) 195 .onDragStart((event)=>{ 196 let data: UDC.PlainText = new UDC.PlainText(); 197 data.abstract = 'this is abstract'; 198 data.textContent = 'this is content this is content'; 199 (event as DragEvent).setData(new UDC.UnifiedData(data)); 200 }) 201 }.width('45%') 202 .height('100%') 203 Column() { 204 Text('Drag Target Area') 205 .fontSize(20) 206 .width('100%') 207 .height(40) 208 .margin(10) 209 .backgroundColor('#008888') 210 Image(this.targetImage) 211 .width(this.imageWidth) 212 .height(this.imageHeight) 213 .draggable(true) 214 .margin({left: 15}) 215 .border({color: Color.Black, width: 1}) 216 .allowDrop([UTD.UniformDataType.IMAGE]) 217 .onDrop((dragEvent?: DragEvent)=> { 218 this.getDataFromUdmf((dragEvent as DragEvent), (event:DragEvent) => { 219 let records: Array<UDC.UnifiedRecord> = event.getData().getRecords(); 220 let rect: Rectangle = event.getPreviewRect(); 221 this.imageWidth = Number(rect.width); 222 this.imageHeight = Number(rect.height); 223 this.targetImage = (records[0] as UDC.Image).imageUri; 224 event.useCustomDropAnimation = false; 225 animateTo({duration: 1000}, ()=>{ 226 this.imageWidth = 100; 227 this.imageHeight = 100; 228 this.imgState = Visibility.None; 229 }) 230 event.setResult(DragResult.DRAG_SUCCESSFUL); 231 }) 232 }) 233 234 Text(this.targetText) 235 .width('100%') 236 .height(100) 237 .border({color: Color.Black, width: 1}) 238 .margin(15) 239 .allowDrop([UTD.UniformDataType.TEXT]) 240 .onDrop((dragEvent?: DragEvent)=>{ 241 this.getDataFromUdmf((dragEvent as DragEvent), (event:DragEvent) => { 242 let records:Array<UDC.UnifiedRecord> = event.getData().getRecords(); 243 let plainText:UDC.PlainText = records[0] as UDC.PlainText; 244 this.targetText = plainText.textContent; 245 }) 246 }) 247 248 Video({src: this.videoSrc, previewUri: $r('app.media.icon')}) 249 .width('100%') 250 .height(200) 251 .controls(true) 252 .allowDrop([UTD.UniformDataType.VIDEO]) 253 254 Column() { 255 Text(this.abstractContent).fontSize(20).width('100%') 256 Text(this.textContent).fontSize(15).width('100%') 257 }.width('100%').height(100).margin(20).border({color: Color.Black, width: 1}) 258 .allowDrop([UTD.UniformDataType.PLAIN_TEXT]) 259 .onDrop((dragEvent?: DragEvent)=>{ 260 this.getDataFromUdmf((dragEvent as DragEvent), (event:DragEvent) => { 261 let records: Array<UDC.UnifiedRecord> = event.getData().getRecords(); 262 let plainText: UDC.PlainText = records[0] as UDC.PlainText; 263 this.abstractContent = plainText.abstract as string; 264 this.textContent = plainText.textContent; 265 }) 266 }) 267 }.width('45%') 268 .height('100%') 269 .margin({left: '5%'}) 270 } 271 .height('100%') 272 } 273} 274``` 275