@

目录

  • 前言
  • 准备
  • 图片拖拽
  • 落位动效
  • 拖拽背景

前言

看拖拽效果好久嘞, 今天正好有时间跟着HMOS代码工坊来实践一下。

准备

需要了解的一些基础

  • 默认支持拖出能力的组件(可从组件上拖出数据):Search、TextInput、TextArea、RichEditor、Text、Image、Hyperlink,开发者可通过设置这些组件的draggable属性来控制对默认拖拽能力的使用。

  • 默认支持拖入能力的组件(目标组件可响应拖入数据):Search、TextInput、TextArea、RichEditor,开发者可通过设置这些组件的allowDrop属性为null来禁用对默认拖入能力的支持。

  • 其他组件需要开发者将draggable属性设置为true,并在onDragStart等接口中实现数据传输相关内容,才能正确处理拖拽能力。

图片拖拽

我们先来做一个图片拖拽到另一个区域做展示的功能,
首先准备一个图片,使用 Image 组件加载

Image($r('app.media.cat')).fitOriginalSize(true)
  .draggable(true).onDragEnd((event:DragEvent)=>{
  if(event.getResult() == DragResult.DRAG_SUCCESSFUL){
    this.showToast("拖拽成功")
  }else{
    this.showToast("拖拽失败")
  }
})

一个用来接收(展示)拖拽图片的组件

 Image(this.targetImage)
   .fitOriginalSize(true)
   .constraintSize({
   minWidth:"95%",
   minHeight:100
 }).backgroundColor(Color.Gray).borderRadius(12)
   //设置允许落入的数据类型
   .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])

这里的uniformTypeDescriptor是从@kit.ArkData导入,还有一些其他需要导入的对象

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

页面类似这种

当我们长按图片,出现一个放大的动画效果之后,我们就可以拖动图片了。但这时候下面的灰色区域还是不能接收图片。
我们给接收区域加个onDrop事件,这样当我们将图片拖拽到可以接收图片的区域时,图片右上角会有一个绿色的加号。

但这时候松开手指,目标区域是没有接收到我们拖拽的数据的。我们需要在onDrop事件中自己处理数据接收

.onDrop((event?:DragEvent)=>{
  if(event){
    //获取拖拽数据对象
   let dragData:UnifiedData =   event.getData()
    let records: unifiedDataChannel.UnifiedRecord[] = dragData.getRecords();
    if(records){
      //遍历一下数据
      records.forEach((value)=>{
         let types = value.getTypes()

        if (types.includes(uniformTypeDescriptor.UniformDataType.FILE_URI)) {
          const fileUriUds =
            value.getEntry(uniformTypeDescriptor.UniformDataType.FILE_URI) as uniformDataStruct.FileUri;
          let typeDescriptor = uniformTypeDescriptor.getTypeDescriptor(fileUriUds.fileType);
          //拿到的数据是图片类型
          if (typeDescriptor.belongsTo(uniformTypeDescriptor.UniformDataType.IMAGE)) {
            this.targetImage = fileUriUds.oriUri;
          }
        }
      })
    }
  }
})

这时候我们就能完成拖拽了。

落位动效

但在松开手指的时候,图片出现的有点生硬,我们可以使用自定义落位动效,通过动画来消除一下。

 rawImageWidth:Length = 0
 rawImageHeight:Length = 0
 @State targetImageWidth:Length = 0
 @State targetImageHeight:Length = 0

先获取图片展示出来之后需要的宽高

.onAreaChange((oldValue,newValue)=>{
        this.rawImageWidth = newValue.width
        this.rawImageHeight = newValue.height
      }

定义一个缩放动画:

  customDropAnimation =
    () => {
      this.getUIContext().animateTo({ duration: 1000, curve: Curve.EaseOut, playMode: PlayMode.Normal }, () => {
        this.targetImageWidth = this.rawImageWidth;
        this.targetImageHeight = this.rawImageHeight;
      })
    }

onDrop事件中使用

 .onDrop((event?:DragEvent)=>{
   if(event){
     event.useCustomDropAnimation = true;
     event.executeDropAnimation(this.customDropAnimation)
   }
})

现在我们来看下效果

在这里插入图片描述


看起来效果还行。

拖拽背景

有时候我们可能会有自定义拖拽背景的需求,但这里也有一些需要注意的地方:

  • 针对默认支持拖拽能力的组件,如果开发者设置了onDragStart,优先执行onDragStart,并根据执行情况决定是否使用系统默认的拖拽能力,具体规则为:

如果开发者返回了自定义预览图,则不再使用系统默认的拖拽预览图;
如果开发者设置了拖拽数据,则不再使用系统默认填充的拖拽数据。

  • 文本类组件Text、Search、TextInput、TextArea、RichEditor对选中的文本内容进行拖拽时,不支持自定义预览图。
  • 当onDragStart与菜单预览一起使用或使用了默认支持拖拽能力的组件时,预览及菜单项上的自定义内容不支持拖拽。

自定义背景也很简单,我们只需要在onDragStart事件中返回描述背景的DragItemInfo对象即可

  @Builder
  pixelMapBuilder() {
    Column() {
     Image($r('app.media.startIcon')).fitOriginalSize(true)
    }
    .backgroundColor($r('sys.color.comp_background_primary'))
    .borderRadius(16)
  }

 .onDragStart(()=>{
   let dragItemInfo: DragItemInfo = {
     builder: () => {
       this.pixelMapBuilder()
     },
   };
   return dragItemInfo;
 })

在这里插入图片描述


HMOS代码工坊APP已可在华为应用市场下载:
https://appgallery.huawei.com/app/detail?id=com.huawei.hmos.world&channelId=SHARE

【 更多精彩内容,请关注公众号:【名称:HarmonyOS开发者技术,ID:HarmonyOS_Dev】;也欢迎加入鸿蒙开发者交流群:https://work.weixin.qq.com/gm/48f89e7a4c10206e053e01ad124004a0

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐