HarmonyOS鸿蒙Next中拖动组件

HarmonyOS鸿蒙Next中拖动组件 Grid组件编辑模式打开后,仍然不可以拖动组件该如何解决

4 回复

【背景知识】

  • 设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem。详情请参考editMod接口文档
  • hitTestBehavior属性用于设置不同的触摸测试响应模式,影响触摸测试收集结果及后续触屏事件分发。具体影响参考HitTestMode枚举说明

【问题定位】

常见场景:editMode是Grid组件的API,控制整个Grid组件是否能编辑。出现editMode打开了依然无法拖动,是因为拖动事件跟onClick事件发生了冲突。

【解决方案】

根据以上分析,解决方案如下:

  1. 不同的元素,设置不同的HitTestMode。
// Grid默认的首个与元素是-1
@State selectMedias: Array<string> = ["-1"]
@Builder
itemGrid(item: string, index: number) {
  // -1元素即时+号图片只需要加上onclick事件,无需其他特殊处理,HitTestMode的默认值就是Default
  if (item === "-1") {
    Image($r('app.media.imagePicker'))
      .objectFit(ImageFit.Cover)
      // onclick事件,添加图片到Grid
      .onClick(() => {
        this.selectImages({
          MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE,
          maxSelectNumber: this.maxSelectPics - (this.selectMedias.length - 1)
        }, (photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
          this.selectMedias = this.selectMedias.concat(photoSelectResult.photoUris)
          if (this.selectMedias.length > this.maxSelectPics) {
            this.selectMedias = this.selectMedias.filter(data => data !== "-1");
          }
        })
      })
  } else {
    // 通过onclick事件添加进来的图片,设置hitTestBehavior为HitTestMode.None
    Image(item)
      .hitTestBehavior(HitTestMode.None)
  }
}
  1. 拖拽图片后,根据拖拽的位置序号来进行重新排序。
.onItemDragStart((event:
if (this.selectMedias[itemIndex] !== "-1") {
  // 在onItemDragStart函数返回自定义组件,可在拖拽过程中显示此自定义组件。
  return this.itemDragGrid(this.selectMedias[itemIndex], itemIndex)
}
})
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
  // 执行gridItem切换操作
  if (isSuccess && insertIndex < this.selectMedias.length) {
    // 点击选择图标不进行交换
    if (this.selectMedias[itemIndex] === "-1") {
      return
    }
    // 修改图片的index达到重新排序的效果
    this.changeIndex(itemIndex, insertIndex)
  }
})
}

/**
 * 交换应用位置函数
 * @param itemIndex 目标网格元素的index
 * @param insertIndex 被切换网格元素的index
 */
changeIndex(itemIndex: number, insertIndex: number): void {
  this.selectMedias.splice(insertIndex, 0, this.selectMedias.splice(itemIndex, 1)[0])
}
  1. 拖拽过程中显示自定义组件。
@Builder
// 根据当前被拖拽的Item,封装定义组件
itemDragGrid(item: string, index: number) {
  Image(item)
    .objectFit(ImageFit.Cover)
    .width(this.imageWH)
    .height(this.imageWH)
    .borderRadius(4)
}

更多关于HarmonyOS鸿蒙Next中拖动组件的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


【背景知识】

Grid:网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。

【参考方案】

可参考频道选择示例,通过Grid组件实现添加、删除频道以及对频道进行拖动排序等功能。

  1. 通过bindSheet方法给组件绑定半模态页面,点击图标后唤起频道选择页面。
TabsWithBarIcon({ tabArray: this.mySubscriptionList, canShowEditSheet: this.canShowSheet })
  // 绑定半模态页面
  .bindSheet($$this.canShowSheet, this.channelEditSheetBuilder(), {});

Image($r('sys.media.ohos_ic_public_add'))
  .onClick(() => {
    this.showEditSheet = true;  // 打开半模态页面
  });
  1. 通过设置editMode属性进入Grid组件编辑模式,并设置supportAnimation属性开启GridItem拖拽动画。

  2. onItemDragStart事件中,设置拖拽过程中显示的组件样式。

  3. onItemDrop事件中,获取拖拽起始位置itemIndex和插入位置insertIndex,并实现移动元素位置的逻辑。

Grid() {
  // 网格元素
}
.editMode(this.isEditMode)
.supportAnimation(true) // 开启拖拽动画
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => {
  // 跟随手指拖动时所渲染的网格内容
  return this.gridDragBuilder(this.mySubscriptionList[itemIndex].name);
})
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
  if (isSuccess) {
    // 成功释放后,移动元素位置
    moveElement(this.mySubscriptionList, itemIndex, insertIndex);
  }
});

在HarmonyOS Next中,拖动组件通过ArkUI框架的拖拽事件实现。使用onDragStartonDragonDrop等事件处理拖拽生命周期。组件需设置draggable属性为true来启用拖拽功能。拖拽数据通过DragEvent传递,支持自定义数据格式。系统提供拖拽预览效果和动画,无需额外配置。拖拽操作可在同一应用或跨应用间进行,遵循鸿蒙的安全权限机制。

在HarmonyOS Next中,若Grid组件的编辑模式已开启但无法拖动组件,建议按以下步骤排查:

  1. 检查拖动手势配置
    确保GridItem已设置正确的拖拽事件监听器(如onDragStart),且未与其他手势冲突。

  2. 验证编辑模式状态
    确认Grid的editable属性为true,且未因数据绑定问题被重置为false

  3. 排查布局约束
    检查GridItem是否被父容器限制布局(如固定宽高或位置锁定),需确保布局支持自由拖拽。

  4. 调试拖拽反馈
    尝试为GridItem添加拖拽时的视觉反馈(如透明度变化),确认拖拽事件是否正常触发。

若问题仍存在,建议提供相关代码片段以便进一步分析。

回到顶部