1# Drag and Drop Control 2 3The drag and drop control attributes set whether a component can respond to drag events. 4 5> **NOTE** 6> 7> The APIs of this module are supported since API version 10. Updates will be marked with a superscript to indicate their earliest API version. 8 9The ArkUI framework provides default drag and drop capabilities 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). You can also define drag responses by implementing common drag events. 10 11- The following component supports drag actions by default: [Search](ts-basic-components-search.md), [TextInput](ts-basic-components-textinput.md), [TextArea](ts-basic-components-textarea.md), [RichEditor](ts-basic-components-richeditor.md), [Text](ts-basic-components-text.md), [Image](ts-basic-components-image.md), <!--Del-->[FormComponent](ts-basic-components-formcomponent-sys.md), <!--DelEnd-->[Hyperlink](ts-container-hyperlink.md). You can control the default drag behavior by setting the [draggable](ts-universal-attributes-drag-drop.md#draggable) attribute. 12 13- The following component supports drop actions by default: [Search](ts-basic-components-search.md), [TextInput](ts-basic-components-textinput.md), [TextArea](ts-basic-components-textarea.md), [RichEditor](ts-basic-components-richeditor.md). You can disable the default drag behavior by setting the [allowDrop](ts-universal-attributes-drag-drop.md#allowdrop) attribute to **null**. 14 15<!--RP1--><!--RP1End-->To 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**. 16 17> **NOTE** 18> 19> When using the **Text** component, set [copyOption](ts-basic-components-text.md#copyoption9) to **CopyOptions.InApp** or **CopyOptions.LocalDevice**. 20 21## allowDrop 22 23allowDrop(value: Array<UniformDataType> | null) 24 25Sets the type of data that can be dropped to the component. 26 27**Atomic service API**: This API can be used in atomic services since API version 11. 28 29**System capability**: SystemCapability.ArkUI.ArkUI.Full 30 31**Parameters** 32 33| Name| Type | Mandatory| Description | 34| ------ | ------------------------------------------------------------ | ---- | ----------------------------------------------- | 35| value | Array\<[UniformDataType](../../apis-arkdata/js-apis-data-uniformTypeDescriptor.md#uniformdatatype)> \| null<sup>12+</sup> | Yes | Type of data that can be dropped to the component. Since API version 12, this parameter can be set to **null** to make the component reject all data types.<br>Default value: empty| 36 37## draggable 38 39draggable(value: boolean) 40 41Sets whether the component is draggable. 42 43**Atomic service API**: This API can be used in atomic services since API version 11. 44 45**System capability**: SystemCapability.ArkUI.ArkUI.Full 46 47**Parameters** 48 49| Name| Type | Mandatory| Description | 50| ------ | ------- | ---- | ---------------------------------------------- | 51| value | boolean | Yes | Whether the component is draggable.<br>Default value: **false**| 52 53## dragPreview<sup>11+</sup> 54 55dragPreview(value: CustomBuilder | DragItemInfo | string) 56 57Sets the preview displayed when the component is dragged. 58 59**Atomic service API**: This API can be used in atomic services since API version 12. 60 61**System capability**: SystemCapability.ArkUI.ArkUI.Full 62 63**Parameters** 64 65| Name| Type | Mandatory| Description | 66| ------ | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 67| value | [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](ts-universal-events-drag-drop.md#dragiteminfo) \| string<sup>12+</sup> | Yes | Preview displayed when the component is dragged. This attribute has effect for **onDragStart** only.<br>If the component supports drag and drop and a preview is specified through [bindContextMenu](ts-universal-attributes-menu.md#bindcontextmenu8), that specified preview is displayed when the component is dragged. The priority of the background image returned in [onDragStart](ts-universal-events-drag-drop.md#onDragStart) is lower than that of the preview set in [dragPreview](ts-universal-attributes-drag-drop.md#dragPreview11). This means that, once set, the latter will be used in place of the former. Because [CustomBuilder](ts-types.md#custombuilder8) can be used only after offline rendering, it may increase performance overhead and latency. In light of this, you are advised to use [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7) in [DragItemInfo](ts-universal-events-drag-drop.md#dragiteminfo) to set the preview.<br> When an ID of the string type is passed in, the snapshot of the component assigned the ID is used as the preview image. If the component assigned the ID cannot be found or its **Visibility** attribute is set to **none** or **hidden**, a snapshot of the current component is used as the preview image. Currently, snapshots do not support visual effects, such as brightness, shadow, blur, and rotation.<br>Default value: empty<br>| 68 69## dragPreviewOptions<sup>11+</sup> 70 71dragPreviewOptions(value: DragPreviewOptions, options?: DragInteractionOptions) 72 73Sets the processing mode of the drag preview and the display of the number badge during dragging. The **onItemDragStart** dragging mode is not supported. 74 75**Atomic service API**: This API can be used in atomic services since API version 12. 76 77**System capability**: SystemCapability.ArkUI.ArkUI.Full 78 79**Parameters** 80 81| Name| Type | Mandatory| Description | 82| ------ | -------------------------------------------------------------- | ---- | ------------------------------------------------------------ | 83| value | [DragPreviewOptions](#dragpreviewoptions11)<sup>11+</sup> | Yes | Processing mode of the drag preview and the display of the number badge during dragging.<br>Default value: empty| 84| options<sup>12+</sup>| [DragInteractionOptions](#draginteractionoptions12)<sup>12+</sup>| No | Interaction mode of the drag preview.<br>Default value: empty| 85 86## DragPreviewOptions<sup>11+</sup> 87 88**Atomic service API**: This API can be used in atomic services since API version 12. 89 90| Name| Type| Mandatory| Description| 91| -------- | -------- | -------- | -------- | 92| mode | [DragPreviewMode](#dragpreviewmode11) \| Array<[DragPreviewMode](#dragpreviewmode11)><sup>12+</sup>| No| How the background image is processed when the component is dragged.<br>Default value: **DragPreviewMode.AUTO**<br>If **DragPreviewMode.AUTO** is along with other enum values, the setting takes precedence with **DragPreviewMode.AUTO**, and other enum values do not take effect.| 93| numberBadge<sup>12+</sup> | boolean \| number | No| Whether to display the number badge or the number displayed on the badge. For a number badge, the value range is [0, 2<sup>31</sup>-1]. Values outside this range will be processed as the default state. If the value specified is a floating-point number, only the integer part is displayed.<br>**NOTE**<br>When multiple items are dragged, use this API to set the number of items dragged.<br>Default value: **true**| 94| modifier<sup>12+</sup> | [ImageModifier](ts-universal-attributes-attribute-modifier.md)| No| Style modifier to apply to the drag preview. You can use the attributes and styles supported by the image component to configure the drag preview style (see example 6). Currently, opacity, shadow, background blur, and rounded corners are supported. This parameter does not work for text dragging, which only supports the default effect.<br>1. Opacity<br>Use the [opacity](ts-universal-attributes-opacity.md#opacity) attribute to set the opacity. The value ranges from 0 to 1. If the value is set to **0** or left unspecified, it reverts to the default value **0.95**. Setting it to **1** or an invalid value makes the object completely opaque.<br>2. Shadow<br>Use the [shadow](ts-universal-attributes-image-effect.md#shadow) attribute to set the shadow.<br>3. Background blur<br>Use the [backgroundEffect](ts-universal-attributes-background.md#backgroundeffect11) or [backgroundBlurStyle](ts-universal-attributes-background.md#backgroundblurstyle9) attribute to set the background blur. If both are used, **backgroundEffect** takes precedence.<br>4. Rounded corner<br>Use the [border](ts-universal-attributes-border.md#border) or [borderRadius](ts-universal-attributes-border.md#borderRadius) attribute to set rounded corners. If you set rounded corners in both **mode** and **modifier**, the settings in **modifier** prevail.<br>Default value: empty. The attribute cannot be modified.| 95 96## DragPreviewMode<sup>11+</sup> 97 98**Atomic service API**: This API can be used in atomic services since API version 12. 99 100| Name| Value| Description| 101| -------- | ------- | -------- | 102| AUTO | 1 | Enables the system to automatically change the position of the dragged point based on the scenario and apply scaling transformations to the drag preview based on set rules.| 103| DISABLE_SCALE | 2 | Disables the system's scaling behavior for the drag preview.| 104| ENABLE_DEFAULT_SHADOW<sup>12+</sup> | 3 | Enables the default shadow effect for non-text components.| 105| ENABLE_DEFAULT_RADIUS<sup>12+</sup> | 4 | Enables a unified rounded corner effect for non-text components, with the default value of 12 vp. If the custom rounded corner value set by the application is greater than the default value or the value set by **modifier**, the custom value is used.| 106 107## DragInteractionOptions<sup>12+</sup> 108 109**Atomic service API**: This API can be used in atomic services since API version 12. 110 111| Name| Type| Mandatory| Description| 112| -------- | -------- | -------- | -------- | 113| isMultiSelectionEnabled | boolean | No| Whether to enable multiselect for the drag preview. This parameter takes effect only for the [grid items](ts-container-griditem.md) and [list items](ts-container-listitem.md) in the [Grid](ts-container-grid.md) and [List](ts-container-list.md) containers.<br>When multiselect is enabled for an item, the child components of the item cannot be dragged. The precendence levels of drag previews for multiselect, from high to low, are as follows: preview specified through a string value in [dragPreview](#dragpreview11), preview specified through **PixelMap** in **dragPreview**, and component snapshot. The Builder format in **dragPreview** is not supported.<br>The context menu bound to the component through [bindContextMenu](ts-universal-attributes-menu.md#bindcontextmenu12) cannot contain the **isShown** parameter.<br>Default value: **false**<br>| 114| defaultAnimationBeforeLifting | boolean | No| Whether to enable the default pressed state animation (compressing in size) of the component before a lift animation starts.<br>Default value: **false**<br>| 115 116## Example 117### Example 1: Allowing Drag and Drop 118 119This example demonstrates how to configure whether a component can be dragged and dropped into by setting **allowDrop** and **draggable**. 120 121```ts 122// xxx.ets 123import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; 124 125@Entry 126@Component 127struct ImageExample { 128 @State uri: string = "" 129 @State AblockArr: string[] = [] 130 @State BblockArr: string[] = [] 131 @State AVisible: Visibility = Visibility.Visible 132 @State dragSuccess :Boolean = false 133 134 build() { 135 Column() { 136 Text('Image drag and drop') 137 .fontSize('30dp') 138 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceAround }) { 139 Image($r('app.media.icon')) 140 .width(100) 141 .height(100) 142 .border({ width: 1 }) 143 .visibility(this.AVisible) 144 .draggable(true) 145 .onDragEnd((event: DragEvent) => { 146 let ret = event.getResult(); 147 if(ret == 0) { 148 console.log("enter ret == 0") 149 this.AVisible = Visibility.Hidden; 150 } else { 151 console.log("enter ret != 0") 152 this.AVisible = Visibility.Visible; 153 } 154 }) 155 } 156 .margin({ bottom: 20 }) 157 Row() { 158 Column(){ 159 Text('Invalid drop target') 160 .fontSize('15dp') 161 .height('10%') 162 List(){ 163 ForEach(this.AblockArr, (item:string, index) => { 164 ListItem() { 165 Image(item) 166 .width(100) 167 .height(100) 168 .border({width: 1}) 169 } 170 .margin({ left: 30 , top : 30}) 171 }, (item:string) => item) 172 } 173 .height('90%') 174 .width('100%') 175 .allowDrop([uniformTypeDescriptor.UniformDataType.TEXT]) 176 .onDrop((event?: DragEvent, extraParams?: string) => { 177 this.uri = JSON.parse(extraParams as string).extraInfo; 178 this.AblockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri); 179 console.log("ondrop not udmf data"); 180 }) 181 .border({width: 1}) 182 } 183 .height("50%") 184 .width("45%") 185 .border({ width: 1 }) 186 .margin({ left: 12 }) 187 Column(){ 188 Text('Valid drop target') 189 .fontSize('15dp') 190 .height('10%') 191 List(){ 192 ForEach(this.BblockArr, (item:string, index) => { 193 ListItem() { 194 Image(item) 195 .width(100) 196 .height(100) 197 .border({width: 1}) 198 } 199 .margin({ left: 30 , top : 30}) 200 }, (item:string) => item) 201 } 202 .border({width: 1}) 203 .height('90%') 204 .width('100%') 205 .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) 206 .onDrop((event?: DragEvent, extraParams?: string) => { 207 console.log("enter onDrop") 208 let dragData:UnifiedData = (event as DragEvent).getData() as UnifiedData; 209 if(dragData != undefined) { 210 let arr:Array<unifiedDataChannel.UnifiedRecord> = dragData.getRecords(); 211 if(arr.length > 0) { 212 let image = arr[0] as unifiedDataChannel.Image; 213 this.uri = image.imageUri; 214 this.BblockArr.splice(JSON.parse(extraParams as string).insertIndex, 0, this.uri); 215 } else { 216 console.log(`dragData arr is null`) 217 } 218 } else { 219 console.log(`dragData is undefined`) 220 } 221 console.log("ondrop udmf data"); 222 this.dragSuccess = true 223 }) 224 } 225 .height("50%") 226 .width("45%") 227 .border({ width: 1 }) 228 .margin({ left: 12 }) 229 } 230 }.width('100%') 231 } 232} 233``` 234 235 236 237### Example 2: Setting the Drag Preview 238 239This example demonstrates how to configure the preview displayed during the drag process using **dragPreview**. 240 241```ts 242// xxx.ets 243@Entry 244@Component 245struct DragPreviewDemo{ 246 @Builder dragPreviewBuilder() { 247 Column() { 248 Text("dragPreview") 249 .width(150) 250 .height(50) 251 .fontSize(20) 252 .borderRadius(10) 253 .textAlign(TextAlign.Center) 254 .fontColor(Color.Black) 255 .backgroundColor(Color.Pink) 256 } 257 } 258 259 @Builder MenuBuilder() { 260 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 261 Text("menu item 1") 262 .fontSize(15) 263 .width(100) 264 .height(40) 265 .textAlign(TextAlign.Center) 266 .fontColor(Color.Black) 267 .backgroundColor(Color.Pink) 268 Divider() 269 .height(5) 270 Text("menu item 2") 271 .fontSize(15) 272 .width(100) 273 .height(40) 274 .textAlign(TextAlign.Center) 275 .fontColor(Color.Black) 276 .backgroundColor(Color.Pink) 277 } 278 .width(100) 279 } 280 281 build() { 282 Row() { 283 Column() { 284 Image('/resource/image.jpeg') 285 .width("30%") 286 .draggable(true) 287 .bindContextMenu(this.MenuBuilder, ResponseType.LongPress) 288 .onDragStart(() => { 289 console.log("Image onDragStart") 290 }) 291 .dragPreview(this.dragPreviewBuilder) 292 } 293 .width("100%") 294 } 295 .height("100%") 296 } 297} 298``` 299 300 301 302### Example 3: Setting the Drag Preview Style 303 304This example demonstrates how to set default shadows and unified rounded corners by configuring **dragPreviewOptions** with **ENABLE_DEFAULT_SHADOW** and **ENABLE_DEFAULT_RADIUS**. 305 306```ts 307// xxx.ets 308@Entry 309@Component 310struct dragPreviewOptionsDemo{ 311 build() { 312 Row() { 313 Column() { 314 Image('/resource/image.jpeg') 315 .margin({ top: 10 }) 316 .width("100%") 317 .draggable(true) 318 .dragPreviewOptions({ mode: DragPreviewMode.AUTO }) 319 Image('/resource/image.jpeg') 320 .margin({ top: 10 }) 321 .width("80%") 322 .border({ radius: { topLeft: 1, topRight: 2, bottomLeft: 4, bottomRight: 8 } }) 323 .draggable(true) 324 .dragPreviewOptions({ mode: [ DragPreviewMode.ENABLE_DEFAULT_SHADOW, DragPreviewMode.ENABLE_DEFAULT_RADIUS ] }) 325 } 326 .width("100%") 327 .height("100%") 328 } 329 } 330} 331``` 332 333 334 335 336### Example 4: Enabling Multiselect for Dragging 337 338This example demonstrates how to enable multiselect for dragging in a **Grid** component by configuring **isMultiSelectionEnabled**. 339 340```ts 341@Entry 342@Component 343struct Example { 344 @State numbers: number[] = [0, 1, 2, 3, 4 , 5, 6, 7, 8] 345 build() { 346 Column({ space: 5}) { 347 Grid() { 348 ForEach(this.numbers, (item: number) => { 349 GridItem() { 350 Column() 351 .backgroundColor(Color.Blue) 352 .width('100%') 353 .height('100%') 354 } 355 .width(90) 356 .height(90) 357 .selectable(true) 358 .selected(true) 359 .dragPreviewOptions({}, {isMultiSelectionEnabled:true}) 360 .onDragStart(()=>{ 361 362 }) 363 }, (item: string) => item) 364 } 365 .columnsTemplate('1fr 1fr 1fr') 366 .rowsTemplate('1fr 1fr 1fr') 367 .height(300) 368 } 369 .width('100%') 370 } 371} 372``` 373 374 375 376### Example 5: Enabling the Default Pressed State Animation 377 378This example demonstrates how to enable the default pressed state animation for a **Grid** component by configuring **defaultAnimationBeforeLifting**. 379 380```ts 381@Entry 382@Component 383struct Example { 384 @State numbers: number[] = [0, 1, 2, 3, 4 , 5, 6, 7, 8] 385 build() { 386 Column({ space: 5}) { 387 Grid() { 388 ForEach(this.numbers, (item: number) => { 389 GridItem() { 390 Column() 391 .backgroundColor(Color.Blue) 392 .width('100%') 393 .height('100%') 394 } 395 .width(90) 396 .height(90) 397 .selectable(true) 398 .selected(true) 399 .dragPreviewOptions({}, {isMultiSelectionEnabled:true, defaultAnimationBeforeLifting:true}) 400 .onDragStart(()=>{ 401 402 }) 403 }, (item: string) => item) 404 } 405 .columnsTemplate('1fr 1fr 1fr') 406 .rowsTemplate('1fr 1fr 1fr') 407 .height(300) 408 } 409 .width('100%') 410 } 411} 412``` 413 414 415 416### Example 6: Customizing the Preview Style 417 418This example demonstrates how to customize the preview style for an **Image** component by configuring **ImageModifier**. 419 420```ts 421// xxx.ets 422import { ImageModifier } from '@kit.ArkUI' 423 424@Entry 425@Component 426struct dragPreviewOptionsDemo{ 427 @State myModifier: ImageAttribute = new ImageModifier().opacity(0.5) 428 @State vis: boolean = true 429 @State changeValue: string = '' 430 @State submitValue: string = '' 431 @State positionInfo: CaretOffset = { index: 0, x: 0, y: 0 } 432 controller: SearchController = new SearchController() 433 @State OpacityIndex: number = 0 434 @State OpacityList:(number | undefined | null)[]=[ 435 0.3,0.5,0.7,1,-50,0,10,undefined,null 436 ] 437 build() { 438 Row() { 439 Column() { 440 Text(this.OpacityList[this.OpacityIndex] + "") 441 Button("Opacity") 442 .onClick(()=> { 443 this.OpacityIndex++ 444 if(this.OpacityIndex > this.OpacityList.length - 1){ 445 this.OpacityIndex = 0 446 } 447 }) 448 Image($r('app.media.image')) 449 .margin({ top: 10 }) 450 .width("100%") 451 .draggable(true) 452 .dragPreviewOptions({modifier: this.myModifier.opacity(this.OpacityList[this.OpacityIndex]) as ImageModifier}) 453 } 454 .width("50%") 455 .height("50%") 456 } 457 } 458} 459``` 460 461 462 463### Example 7: Configuring Image Dragging Settings 464 465This example shows the settings for different types of images (online image resources, local image resources, and PixelMap) during drag operations. 466The **ohos.permission.INTERNET** permission is required for using online images. For details about how to apply for a permission, see [Declaring Permissions](../../../security/AccessToken/declare-permissions.md). 467 468```ts 469// xxx.ets 470import { uniformTypeDescriptor, unifiedDataChannel } from '@kit.ArkData'; 471import { image } from '@kit.ImageKit'; 472import { request } from '@kit.BasicServicesKit'; 473import { common } from '@kit.AbilityKit'; 474import { fileIo } from '@kit.CoreFileKit'; 475import { buffer } from '@kit.ArkTS'; 476import { BusinessError } from '@kit.BasicServicesKit'; 477 478@Entry 479@Component 480struct ImageDrag { 481 @State targetImage1: string | PixelMap | null = null; 482 @State targetImage2: string | PixelMap | null = null; 483 @State targetImage3: string | PixelMap | null = null; 484 context = getContext(this) as common.UIAbilityContext; 485 filesDir = this.context.filesDir; 486 487 public async createPixelMap(pixelMap: unifiedDataChannel.SystemDefinedPixelMap): Promise<image.PixelMap | null> { 488 let mWidth: number = (pixelMap.details?.width ?? -1) as number; 489 let mHeight: number = (pixelMap.details?.width ?? -1) as number; 490 let mPixelFormat: image.PixelMapFormat = 491 (pixelMap.details?.['pixel-format'] ?? image.PixelMapFormat.UNKNOWN) as image.PixelMapFormat; 492 let mItemPixelMapData: Uint8Array = pixelMap.rawData; 493 const opts: image.InitializationOptions = { 494 editable: false, pixelFormat: mPixelFormat, size: { 495 height: mHeight, 496 width: mWidth 497 } 498 }; 499 const buffer: ArrayBuffer = mItemPixelMapData.buffer.slice(mItemPixelMapData.byteOffset, 500 mItemPixelMapData.byteLength + mItemPixelMapData.byteOffset); 501 try { 502 let pixelMap: image.PixelMap = await image.createPixelMap(buffer, opts); 503 return pixelMap; 504 } catch (err) { 505 console.error('dragtest--> getPixelMap', err); 506 return null; 507 } 508 } 509 510 build() { 511 Column() { 512 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center }) { 513 // Drag an online image. 514 Column() { 515 Text('Online Image').fontSize(14) 516 Image('https://www.example.com/xxx.png') // Enter a specific online image URL. 517 .objectFit(ImageFit.Contain).draggable(true) 518 .onDragStart(() => {}) 519 .width(100).height(100) 520 } 521 .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted }) 522 .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) 523 524 // Drag a local image. 525 Column() { 526 Text('Local Image').fontSize(14) 527 Image($r('app.media.example')) 528 .objectFit(ImageFit.Contain).draggable(true) 529 .onDragStart(() => {}) 530 .width(100).height(100) 531 } 532 .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted }) 533 .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) 534 535 // Drag a PixelMap object. 536 Column() { 537 Text('PixelMap').fontSize(14) 538 Image(this.context.resourceManager.getDrawableDescriptor($r('app.media.example').id).getPixelMap()) 539 .objectFit(ImageFit.Contain).draggable(true) 540 .onDragStart(() => {}) 541 .width(100).height(100) 542 } 543 .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted }) 544 .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) 545 } 546 547 // Set the drop data type to Image. 548 Text('Data type is Image').fontSize(14).margin({ top: 10 }) 549 Column() { 550 Image(this.targetImage1) 551 .objectFit(ImageFit.Contain) 552 .width('70%').height('70%') 553 .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) 554 .onDrop((event: DragEvent, extraParams: string) => { 555 // Obtain the image through extraParams. 556 let arr: Record<string, object> = JSON.parse(extraParams) as Record<string, object>; 557 let uri = arr['extraInfo']; 558 if (typeof uri == 'string') { 559 this.targetImage1 = uri; 560 561 try { 562 request.downloadFile(this.context, { 563 url: uri, 564 filePath: this.filesDir + '/example.png' 565 }).then((downloadTask: request.DownloadTask) => { 566 let file = fileIo.openSync(this.filesDir + '/example.png', fileIo.OpenMode.READ_WRITE); 567 let arrayBuffer = new ArrayBuffer(1024); 568 let readLen = fileIo.readSync(file.fd, arrayBuffer); 569 let buf = buffer.from(arrayBuffer, 0, readLen); 570 console.info(`The content of file: ${buf.toString()}`); 571 fileIo.closeSync(file); 572 }) 573 } catch (error) {} 574 } 575 }) 576 } 577 .width('70%').height('25%') 578 .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted }) 579 .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) 580 581 Column() { 582 Image(this.targetImage2) 583 .objectFit(ImageFit.Contain) 584 .width('70%').height('70%') 585 .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) 586 .onDrop((event: DragEvent, extraParams: string) => { 587 // Obtain the image through uniformTypeDescriptor. 588 let data: UnifiedData = event.getData(); 589 let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords(); 590 if (records[0].getType() ===uniformTypeDescriptor.UniformDataType.IMAGE) { 591 let image: unifiedDataChannel.Image = records[0] as unifiedDataChannel.Image; 592 this.targetImage2 = image.imageUri; 593 } 594 }) 595 } 596 .width('70%').height('25%') 597 .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted }) 598 .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) 599 600 // Set the drop data type to PixelMap. 601 Text('Data type is PixelMap').fontSize(14).margin({ top: 10 }) 602 Column() { 603 Image(this.targetImage3) 604 .objectFit(ImageFit.Contain) 605 .width('70%').height('70%') 606 .allowDrop([uniformTypeDescriptor.UniformDataType.OPENHARMONY_PIXEL_MAP]) 607 .onDrop(async (event: DragEvent, extraParams: string) => { 608 // Obtain the image through uniformTypeDescriptor. 609 let data: UnifiedData = event.getData(); 610 let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords(); 611 if (records[0].getType() ===uniformTypeDescriptor.UniformDataType.OPENHARMONY_PIXEL_MAP) { 612 let record: unifiedDataChannel.SystemDefinedPixelMap = records[0] as unifiedDataChannel.SystemDefinedPixelMap; 613 this.targetImage3 = await this.createPixelMap(record); 614 615 // Save data to local storage. 616 const imagePackerApi = image.createImagePacker(); 617 let packOpts : image.PackingOption = { format: "image/jpeg", quality:98 }; 618 const path : string = this.context.cacheDir + "/pixel_map.jpg"; 619 let file = fileIo.openSync(path, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE); 620 imagePackerApi.packToFile(this.targetImage3, file.fd, packOpts).then(() => { 621 // Pack the image into the file. 622 }).catch((error : BusinessError) => { 623 console.error('Failed to pack the image. And the error is: ' + error); 624 }) 625 } 626 }) 627 } 628 .width('70%').height('25%') 629 .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted }) 630 .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center) 631 632 }.width('100%').height('100%') 633 } 634} 635``` 636 637 638