鸿蒙开发中 拖拽事件onDrop的使用

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、拖拽事件核心概念

1. 功能定位
  • 作用:实现组件间数据传递与交互,支持本地/跨应用拖拽(如文件传输、列表排序)。
  • 触发条件
    • 手势拖拽:长按≥500ms且移动≥10vp触发 。
    • 鼠标拖拽:左键移动≥1vp触发 。
2. 核心流程

    participant 拖出组件
    participant 拖入目标
    拖出组件->>拖入目标: onDragStart (设置数据/背板图)
    拖入目标->>拖入目标: onDragEnter (进入范围)
    拖入目标->>拖入目标: onDragMove (移动时)
    拖入目标->>拖入目标: onDrop (释放处理数据)
    拖出组件->>拖出组件: onDragEnd (结束回调)

二、基础使用与API详解

1. 组件使能与事件绑定
// 使能拖拽(默认支持组件如Text、Image可省略)
Text("拖拽我")
  .draggable(true)
  .onDragStart((event: DragEvent) => {
    // 设置拖拽数据
    let data = new unifiedDataChannel.PlainText();
    data.textContent = "Hello";
    event.setData(new unifiedDataChannel.UnifiedData(data));
    // 返回自定义背板图
    return {
      pixelMap: $r('app.media.drag_icon') // 或使用builder
    };
  });

// 使能拖入
Column()
  .allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT])
  .onDrop((event: DragEvent) => {
    let data = event.getData()?.getRecords()[0] as unifiedDataChannel.PlainText;
    console.log("接收数据:", data.textContent);
    event.setResult(DragResult.DRAG_SUCCESSFUL); // 必须设置结果
  });

关键API

  • draggable:控制拖出能力 。
  • allowDrop:指定接收的数据类型(如IMAGEPLAIN_TEXT) 。
  • onDragStart:必须设置数据(setData)或背板图(DragItemInfo) 。
2. 事件回调全周期
事件触发时机典型应用
onPreDrag拖拽前阶段(如准备浮起动效)预加载数据/动画 
onDragEnter进入目标范围高亮目标区域 
onDragMove在目标范围内移动实时更新位置 
onDragLeave离开目标范围取消高亮
onDrop释放拖拽处理数据(必须调用setResult) 
onDragEnd拖拽结束(无论成功与否)清理状态 

三、高级功能实战

1. 自定义拖拽背板与动效
// 自定义背板图(支持动态生成)
.onDragStart((event) => {
  return {
    builder: () => {
      Column() {
        Text("自定义背板").fontColor(Color.White)
        Image($r('app.media.preview')).width(100)
      }
      .backgroundColor(Color.Blue)
    }
  };
});

// 落位动效(API 12+)
.onDrop((event) => {
  event.useCustomDropAnimation({
    duration: 300,
    curve: Curve.Spring
  });
});

限制:文本类组件不支持背板自定义。

2. 多选拖拽与列表排序
// 多选数据传递
let selectedItems = [1, 2, 3];
event.setData(new UnifiedData(selectedItems.map(id => {
  let item = new unifiedDataChannel.Text();
  item.textContent = `Item_${id}`;
  return item;
})));

// 列表插入位置判断(通过extraParams)
.onDrop((event, extraParams) => {
  let insertIndex = JSON.parse(extraParams).insertIndex; // 来自List组件的自动填充
});

四、性能优化建议

场景优化措施
高频拖拽使用pixelMap替代builder减少渲染 
复杂数据预解析extraParams避免重复计算 
列表拖拽通过insertIndex优化DOM操作 

 五、案例:文件管理器拖拽

@Entry
@Component
struct FileManager {
  @State files: string[] = ["a.jpg", "b.pdf"];
  @State draggedFile: string = "";

  build() {
    List() {
      ForEach(this.files, (file) => {
        ListItem() {
          Text(file)
        }
        .draggable(true)
        .onDragStart(() => {
          this.draggedFile = file;
          return { pixelMap: $r('app.media.file_icon') };
        })
      })
    }
    .allowDrop([uniformTypeDescriptor.UniformDataType.FILE_URI])
    .onDrop((event) => {
      if (this.draggedFile) {
        this.files = this.files.filter(f => f !== this.draggedFile);
        event.setResult(DragResult.DRAG_SUCCESSFUL);
      }
    })
  }
}

六、总结

功能推荐API适用场景
基础拖拽draggable + onDragStart简单数据传递
高级动效useCustomDropAnimation交互动画增强
跨应用拖拽UnifiedData + FileUri文件/资源共享

 

### HTML5 `ondrop` Event Usage and Examples In HTML5, the drag-and-drop API allows elements to be dragged and dropped from one location to another within a web page or even between different applications. The `ondrop` event is triggered when an element that has been dragged is released over a valid drop target. For handling the `ondrop` event effectively: When implementing this functionality, setting up both the draggable item and its potential targets with appropriate attributes ensures proper behavior[^1]. Elements can have their `draggable` attribute set to true so they may participate as items being moved around by users. Meanwhile, destinations where these objects could land must listen specifically for the `dragover`, preventing default actions (to allow drops), followed by listening for the actual dropping via the `ondrop`. Here’s how one might implement such interaction using JavaScript along with some inline styles just for demonstration purposes: ```html <div id="droptarget" style="width:200px;height:200px;border:1px solid black;" ondrop="handleDrop(event)" ondragover="allowDrop(event)"> Drop here... </div> <br/> <img id="dragtarget" src="smiley.gif" draggable="true" ondragstart="startDrag(event)" width="336" height="69"> <script type="text/javascript"> function startDrag(ev) { ev.dataTransfer.setData("text", ev.target.id); } function allowDrop(ev) { ev.preventDefault(); } function handleDrop(ev) { ev.preventDefault(); var data = ev.dataTransfer.getData("text"); ev.target.appendChild(document.getElementById(data)); } </script> ``` This code snippet sets up two functions: One (`startDrag`) prepares what will happen once dragging starts—specifically storing information about which object was picked up; Another pair of handlers manage interactions at destination points during hover (`allowDrop`) and upon release (`handleDrop`). By calling `preventDefault()`, browsers are instructed not to execute any built-in behaviors associated with those events but instead follow custom logic defined inside provided callback methods[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值