1# 拖拽控制 2 3设置组件是否可以响应拖拽事件。 4 5> **说明:** 6> 7> 从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8 9ArkUI框架对以下组件实现了默认的拖拽能力,支持对数据的拖出或拖入响应。开发者也可以通过实现通用拖拽事件来自定义拖拽响应。 10 11- 默认支持拖出能力的组件(可从组件上拖出数据):[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),开发者可通过设置这些组件的[draggable](ts-universal-attributes-drag-drop.md#draggable)属性来控制对默认拖拽能力的使用。 12 13- 默认支持拖入能力的组件(目标组件可响应拖入数据):[Search](ts-basic-components-search.md)、[TextInput](ts-basic-components-textinput.md)、[TextArea](ts-basic-components-textarea.md)、[RichEditor](ts-basic-components-richeditor.md),开发者可通过设置这些组件的[allowDrop](ts-universal-attributes-drag-drop.md#allowdrop)属性为null来禁用对默认拖入能力的支持。 14 15<!--RP1--><!--RP1End-->其他组件需要开发者将draggable属性设置为true,并在onDragStart等接口中实现数据传输相关内容,才能正确处理拖拽。 16 17> **说明:** 18> 19> Text组件需配合[copyOption](ts-basic-components-text.md#copyoption9)一起使用,设置copyOptions为CopyOptions.InApp或者CopyOptions.LocalDevice。 20 21## allowDrop 22 23allowDrop(value: Array<UniformDataType> | null) 24 25设置该组件上允许落入的数据类型。 26 27**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 28 29**系统能力:** SystemCapability.ArkUI.ArkUI.Full 30 31**参数:** 32 33| 参数名 | 类型 | 必填 | 说明 | 34| ------ | ------------------------------------------------------------ | ---- | ----------------------------------------------- | 35| value | Array\<[UniformDataType](../../apis-arkdata/js-apis-data-uniformTypeDescriptor.md#uniformdatatype)> \| null<sup>12+</sup> | 是 | 设置该组件上允许落入的数据类型。从API version 12开始,允许设置成null使该组件不接受所有的数据类型。<br/>默认值:空 | 36 37## draggable 38 39draggable(value: boolean) 40 41设置该组件是否允许进行拖拽。 42 43**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 44 45**系统能力:** SystemCapability.ArkUI.ArkUI.Full 46 47**参数:** 48 49| 参数名 | 类型 | 必填 | 说明 | 50| ------ | ------- | ---- | ---------------------------------------------- | 51| value | boolean | 是 | 设置该组件是否允许进行拖拽。<br/>默认值:false | 52 53## dragPreview<sup>11+</sup> 54 55dragPreview(value: CustomBuilder | DragItemInfo | string) 56 57设置组件拖拽过程中的预览图。 58 59**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 60 61**系统能力:** SystemCapability.ArkUI.ArkUI.Full 62 63**参数:** 64 65| 参数名 | 类型 | 必填 | 说明 | 66| ------ | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 67| value | [CustomBuilder](ts-types.md#custombuilder8) \| [DragItemInfo](ts-universal-events-drag-drop.md#dragiteminfo说明) \| string<sup>12+</sup> | 是 | 设置组件拖拽过程中的预览图,仅在onDragStart拖拽方式中有效。<br/>当组件支持拖拽并同时设置[bindContextMenu](ts-universal-attributes-menu.md#bindcontextmenu8)的预览图时,则长按浮起的预览图以[bindContextMenu](ts-universal-attributes-menu.md#bindcontextmenu8)设置的预览图为准。开发者在[onDragStart](ts-universal-events-drag-drop.md#onDragStart)中返回的背板图优先级低于[dragPreview](ts-universal-attributes-drag-drop.md#dragPreview11)设置的预览图,当设置了[dragPreview](ts-universal-attributes-drag-drop.md#dragPreview11)预览图时,拖拽过程中的背板图使用[dragPreview](ts-universal-attributes-drag-drop.md#dragPreview11)预览图。由于[CustomBuilder](ts-types.md#custombuilder8)需要离线渲染之后才能使用,因此存在一定的性能开销和时延,推荐优先使用 [DragItemInfo](ts-universal-events-drag-drop.md#dragiteminfo说明)中的[PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)方式。<br/> 当传入类型为string的id时,则将id对应组件的截图作为预览图。如果id对应的组件无法查找到,或者id对应的组件Visibility属性设置成none/hidden,则对组件自身进行截图作为拖拽预览图。目前截图不含有亮度、阴影、模糊和旋转等视觉效果。<br/>默认值:空<br/> | 68 69## dragPreviewOptions<sup>11+</sup> 70 71dragPreviewOptions(value: DragPreviewOptions, options?: DragInteractionOptions) 72 73设置拖拽过程中背板图处理模式及数量角标的显示。不支持onItemDragStart拖拽方式。 74 75**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 76 77**系统能力:** SystemCapability.ArkUI.ArkUI.Full 78 79**参数:** 80 81| 参数名 | 类型 | 必填 | 说明 | 82| ------ | -------------------------------------------------------------- | ---- | ------------------------------------------------------------ | 83| value | [DragPreviewOptions](#dragpreviewoptions11)<sup>11+</sup> | 是 | 设置拖拽过程中背板图处理模式及数量角标的显示。<br/>默认值:空 | 84| options<sup>12+</sup>| [DragInteractionOptions](#draginteractionoptions12)<sup>12+</sup>| 否 | 设置拖拽过程中背板图浮起的交互模式。<br/>默认值:空| 85 86## DragPreviewOptions<sup>11+</sup> 87 88**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 89 90| 名称 | 类型 | 必填 | 描述 | 91| -------- | -------- | -------- | -------- | 92| mode | [DragPreviewMode](#dragpreviewmode11枚举说明) \| Array<[DragPreviewMode](#dragpreviewmode11枚举说明)><sup>12+</sup> | 否 | 表示拖拽过程中背板图处理模式。<br/>默认值:DragPreviewMode.AUTO<br/>当组件同时设置DragPreviewMode.AUTO和其它枚举值时,以DragPreviewMode.AUTO为准,其它枚举值设置无效。| 93| numberBadge<sup>12+</sup> | boolean \| number | 否 | 控制数量角标是否显示,或强制设置显示的数量。当设置数量角标时取值范围为[0,2<sup>31</sup>-1],超过取值范围时会按默认状态处理。当设置为浮点数时,只显示整数部分。<br/>**说明:** <br>在多选拖拽场景,需通过该接口设置拖拽对象的数量。<br/>默认值:true | 94| modifier<sup>12+</sup> | [ImageModifier](ts-universal-attributes-attribute-modifier.md)| 否 | 用于配置拖拽背板图的样式Modifier对象,可使用图片组件所支持的属性和样式来配置背板图样式(参考示例6),当前支持透明度,阴影,背景模糊度,圆角。文本拖拽只支持默认效果,不支持通过modifier进行自定义。<br/>1.透明度<br/>通过[opacity](ts-universal-attributes-opacity.md#opacity)设置透明度,不透明度的取值范围为0-1。设置0或不设置时采用默认值0.95,设置1或异常值时不透明。<br/>2.阴影<br/>通过[shadow](ts-universal-attributes-image-effect.md#shadow)设置阴影。<br/>3.背景模糊度<br/>通过[backgroundEffect](ts-universal-attributes-background.md#backgroundeffect11)或[backgroundBlurStyle](ts-universal-attributes-background.md#backgroundblurstyle)设置背景模糊度,如果两者同时设置,以backgroundEffect为准。<br/>4.圆角<br/>通过[border](ts-universal-attributes-border.md#border)或[borderRadius](ts-universal-attributes-border.md#borderRadius)设置圆角,当同时在mode和modifier中设置圆角,mode设置的圆角显示优先级低于modifier设置。<br/>默认值:空,无法修改属性| 95 96## DragPreviewMode<sup>11+</sup>枚举说明 97 98**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 99 100| 名称 | 枚举值 | 描述 | 101| -------- | ------- | -------- | 102| AUTO | 1 | 系统根据拖拽场景自动改变跟手点位置,根据规则自动对拖拽背板图进行缩放变换等。 | 103| DISABLE_SCALE | 2 | 禁用系统对拖拽背板图的缩放行为。 | 104| ENABLE_DEFAULT_SHADOW<sup>12+</sup> | 3 | 启用非文本类组件默认阴影效果。 | 105| ENABLE_DEFAULT_RADIUS<sup>12+</sup> | 4 | 启用非文本类组件统一圆角效果,默认值12vp。当应用自身设置的圆角值大于默认值或modifier设置的圆角时,则显示应用自定义圆角效果。 | 106 107## DragInteractionOptions<sup>12+</sup> 108 109**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 110 111| 名称 | 类型 | 必填 | 描述 | 112| -------- | -------- | -------- | -------- | 113| isMultiSelectionEnabled | boolean | 否 | 表示拖拽过程中背板图是否支持多选聚拢效果。该参数只在[Grid](ts-container-grid.md)和[List](ts-container-list.md)组件中的[GridItem](ts-container-griditem.md)组件和[ListItem](ts-container-listitem.md)组件生效。<br/>当一个item组件设置为多选拖拽时,该组件的子组件不可拖拽。聚拢组件预览图设置的优先级为[dragPreview](#dragpreview11)中的string,dragPreview中的PixelMap,组件自截图,不支持dragPreview中的Builder形式。<br/>不支持组件绑定[bindContextMenu](ts-universal-attributes-menu.md#bindcontextmenu12)中参数存在isShown的模式。<br/>默认值:false<br/> | 114| defaultAnimationBeforeLifting | boolean | 否 | 表示是否启用长按浮起阶段组件自身的默认点按效果(缩小)。<br/>默认值:false <br/> | 115 116## 示例 117### 示例1(允许拖拽和落入) 118 119该示例通过配置allowDrop和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拖拽') 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('不允许释放区域') 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('可释放区域') 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### 示例2(设置预览图) 238 239该示例通过配置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### 示例3(设置背板图样式) 303 304该示例通过配置dragPreviewOptions为ENABLE_DEFAULT_SHADOW和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### 示例4(设置多选拖拽) 337 338该示例通过配置isMultiSelectionEnabled实现Grid组件的多选拖拽效果。 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### 示例5(设置默认点按效果) 377 378该示例通过配置defaultAnimationBeforeLifting实现Grid组件的默认点按效果。 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### 示例6(自定义背板图样式) 417 418该示例通过配置ImageModifier实现Image组件的自定义背板图样式。 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### 示例7(图片拖拽设置) 464 465该示例展示了不同图片(在线图片资源、本地图片资源和PixelMap)在拖拽时组件的设置。 466使用网络图片时,需要申请权限ohos.permission.INTERNET。具体申请方式请参考[声明权限](../../../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 // 在线图片资源拖出 514 Column() { 515 Text('Online Image').fontSize(14) 516 Image('https://www.example.com/xxx.png') // 请填写一个具体的网络图片地址 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 // 本地图片资源拖出 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 // PixelMap拖出 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 // 落入数据类型为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 // 通过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 // 通过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 // 落入数据类型为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 // 通过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 // 落盘到本地 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 // 直接打包进文件 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