简介

该文主要提供图片拖拽的场景及最佳实践示例。

开发环境

DevEco Studio: DevEco Studio NEXT Release(Build Version: 5.0.3.900)

系统: OpenHarmony 5.0.0.71

设备: DAYU200(rk3568)

最佳实践示例

Image组件默认可拖拽,可不设置draggable。

本地图片资源拖拽

import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'

@Entry
@Component
struct DragTest1 {
  @State targetImage: string | PixelMap | null = null;
  controller: RichEditorController = new RichEditorController();
  options: RichEditorOptions = { controller: this.controller };

  build() {
    Column() {
      // 本地图片资源拖出
      Column() {
        Image($r('app.media.icon'))
          .objectFit(ImageFit.Contain).draggable(true)
          .width('70%').height('70%')
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)


      // 本地图片资源拖入
      Column() {
        Image(this.targetImage)
          .objectFit(ImageFit.Contain)
          .width('70%').height('70%')
          .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
          .onDrop((event: DragEvent, extraParams: string) => {
            let data: UnifiedData = event.getData();
            let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
            if (records[0].getType() === uniformTypeDescriptor.UniformDataType.IMAGE) {
              let image: unifiedDataChannel.Image = records[0] as unifiedDataChannel.Image;
              this.targetImage = image.imageUri;
            }
          })
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)

      Column() {
        RichEditor(this.options).draggable(true).width('100%').height('100%')
          .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
          .onDrop((event: DragEvent, extraParams: string) => {
            let data: UnifiedData = event.getData();
            let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
            if (records[0].getType() === uniformTypeDescriptor.UniformDataType.IMAGE) {
              let image: unifiedDataChannel.Image = records[0] as unifiedDataChannel.Image;
              this.controller.addImageSpan(image.imageUri);
            }
          })
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)
    }.width('100%').height('100%')
  }
}

在线图片资源拖拽

加载在线图片资源需要在module.json5中添加网络权限:

"requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      },
]
import { uniformTypeDescriptor } from '@kit.ArkData'
import { image } from '@kit.ImageKit';
import request from '@ohos.request';
import { common } from '@kit.AbilityKit';
import fs from '@ohos.file.fs';
import { buffer } from '@kit.ArkTS';

@Entry
@Component
struct DragTest2 {
  @State targetImage: string | PixelMap | null = null;
  controller: RichEditorController = new RichEditorController();
  options: RichEditorOptions = { controller: this.controller };
  pixelMap: image.PixelMap | undefined = undefined
  context = getContext(this) as common.UIAbilityContext;
  filesDir = this.context.filesDir;

  build() {
    Column() {
      // 在线图片资源拖出
      Column() {
        Image('https://filesamples.com/samples/image/png/sample_640%C3%97426.png')
          .objectFit(ImageFit.Contain).draggable(true)
          .width('70%').height('70%')
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)


      // 在线图片资源拖入
      Column() {
        Image(this.targetImage)
          .objectFit(ImageFit.Contain)
          .width('70%').height('70%')
          .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
          .onDrop((event: DragEvent, extraParams: string) => {
            let arr: Record<string, object> = JSON.parse(extraParams) as Record<string, object>;
            let uri = arr['extraInfo'];
            if (typeof uri == 'string') {
              this.targetImage = uri;

              // 落盘到本地
              request.downloadFile(this.context, {
                url: uri,
                filePath: this.filesDir + '/test.png'
              }).then((downloadTask: request.DownloadTask) => {
                let file = fs.openSync(this.filesDir + '/test.png', fs.OpenMode.READ_WRITE);
                let arrayBuffer = new ArrayBuffer(1024);
                let readLen = fs.readSync(file.fd, arrayBuffer);
                let buf = buffer.from(arrayBuffer, 0, readLen);
                console.info(`The content of file: ${buf.toString()}`);
                fs.closeSync(file);
              })
            }
          })
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)

      Column() {
        RichEditor(this.options).draggable(true).width('100%').height('100%')
          .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
          .onDrop((event: DragEvent, extraParams: string) => {
            let arr: Record<string, object> = JSON.parse(extraParams) as Record<string, object>;
            let uri = arr['extraInfo'];
            if (typeof uri == 'string') {
              this.controller.addImageSpan(uri);
            }
          })
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)
    }.width('100%').height('100%')
  }
}

PixelMap资源拖拽

import { common } from '@kit.AbilityKit'
import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import fs from '@ohos.file.fs';

@Entry
@Component
struct DragTest3 {
  @State targetImage: string | PixelMap | null = null;
  private context = getContext(this) as common.UIAbilityContext;
  filesDir = this.context.filesDir;

  build() {
    Column() {
      // PixelMap拖出
      Column() {
        Image(this.context.resourceManager.getDrawableDescriptor($r('app.media.startIcon').id).getPixelMap())
          .objectFit(ImageFit.Contain).draggable(true)
          .width('70%').height('70%')
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)


      // PixelMap拖入
      Column() {
        Image(this.targetImage)
          .objectFit(ImageFit.Contain)
          .width('70%').height('70%')
          .allowDrop([uniformTypeDescriptor.UniformDataType.OPENHARMONY_PIXEL_MAP])
          .onDrop(async (event: DragEvent, extraParams: string) => {
            let data: UnifiedData = event.getData();
            let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
            if (records[0].getType() === uniformTypeDescriptor.UniformDataType.OPENHARMONY_PIXEL_MAP) {
              let record: unifiedDataChannel.SystemDefinedPixelMap = (records[0]) as unifiedDataChannel.SystemDefinedPixelMap;
              this.targetImage = await this.createPixelMap(record);

              // 落盘到本地
              const imagePackerApi = image.createImagePacker();
              let packOpts : image.PackingOption = { format:"image/jpeg", quality:98 };
              const path : string = this.context.cacheDir + "/pixel_map.jpg";
              let file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
              imagePackerApi.packToFile(this.targetImage, file.fd, packOpts).then(() => {
                // 直接打包进文件
              }).catch((error : BusinessError) => {
                console.error('Failed to pack the image. And the error is: ' + error);
              })
            }
          })
      }
      .width('70%').height('30%')
      .border({ width: 2, color: Color.Gray, radius: 5, style: BorderStyle.Dotted })
      .alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)
    }.width('100%').height('100%')
  }

  public async createPixelMap(pixelMap: unifiedDataChannel.SystemDefinedPixelMap): Promise<image.PixelMap | null> {
    let mWidth: number = (pixelMap.details?.width ?? -1) as number;
    let mHeight: number = (pixelMap.details?.height ?? -1) as number;
    let mPixelFormat: image.PixelMapFormat =
      (pixelMap.details?.['pixel-format'] ?? image.PixelMapFormat.UNKNOWN) as image.PixelMapFormat;
    let mItemPixelMapData: Uint8Array = pixelMap.rawData;
    const opts: image.InitializationOptions = {
      editable: false, pixelFormat: mPixelFormat, size: {
        height: mHeight,
        width: mWidth
      }
    };
    const buffer: ArrayBuffer = mItemPixelMapData.buffer.slice(mItemPixelMapData.byteOffset,
      mItemPixelMapData.byteLength + mItemPixelMapData.byteOffset);
    try {
      let pixelMap: image.PixelMap = await image.createPixelMap(buffer, opts);
      return pixelMap;
    } catch (err) {
      console.error('dragtest--> getPixelMap', err);
      return null;
    }
  }
}
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐