HarmonyOS鸿蒙Next中全屏范围内的拖拽都可见的拖拽排序有哪些方法

HarmonyOS鸿蒙Next中全屏范围内的拖拽都可见的拖拽排序有哪些方法 在全屏范围内的拖拽都可见的拖拽排序有哪些方法

List内ForEach的onmove方法和Grid的拖拽排序,拖拽起后的预览图只能在组件范围内显示,有什么方案可以在整个页面内显示吗

5 回复

【解决方案】 1、在onItemDragStart回调中设置拖拽过程中显示的内容。 2、在onItemDrop中通过itemIndex获取拖拽起始位置,insertIndex获取目标位置,并在onItemDrop中调用changeListItemIndex函数完成交换数组位置。 详见官网示例

更多关于HarmonyOS鸿蒙Next中全屏范围内的拖拽都可见的拖拽排序有哪些方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


1.手势的出发范围和你的容器有关,你只是在子组件里面设置生效范围只会在组件内,不过这时候楼主可以尝试更改热区: 触摸热区设置-触摸交互控制-交互属性-通用属性-ArkTS组件-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

2.想要做全局的效果以Navigagation为例,放在窗口加载的页面最上面一层,现在下面的示例就是在最上面一层,需要增加拖拽效果可以参考一下悬浮窗的实现:悬浮窗效果-关键场景示例-影音娱乐类行业实践-行业实践 - 华为HarmonyOS开发者

build() {
  // @Entry中需要再套一层容器组件,Column或者Stack
  RelativeContainer() {
    // 使用HMNavigation容器
    HMNavigation({
      navigationId: NavigationId,
      homePageUrl: HomePage,
      options: {
        standardAnimator: pageAnimator.standardAnim,
        dialogAnimator: pageAnimator.dialogAnim,
        modifier: this.modifier
      }
    })
      .onAppear(() => {
        // AppStorage.setOrCreate(StorageConstant.IS_MAINPAGE_SHOW, true)
      }).onTouch((event) => {
      if (event.type == TouchType.Down) {

      }
    })

    Column() {
 //最上层的内容
    }
    .translate({ x: this.translateX })
    .animation({
      duration: 500,
      onFinish: () => {
        // this.translateFinish = true
      }
    })
    .width(64)
    .height(120)
    .padding({ top: 12, bottom: 12 })
    .alignItems(HorizontalAlign.Center)
    .shadow(ShadowStyle.OUTER_DEFAULT_MD)
    .alignRules({
      bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
      right: { anchor: "__container__", align: HorizontalAlign.End }
    })
    .margin({ bottom: 250 })
    .backgroundColor(Color.White)
    .borderRadius(16)
    .onClick(() => {
      this.translateX = Math.abs(this.translateX - 45)
    })
    .visibility(FloatWindow.isShow() ? Visibility.Visible : Visibility.Hidden)

  }
  .size(matchSize)
  .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])

}

通过长按手势+滑动手势组合实现全屏拖拽,结合显式动画和悬浮层控制

1/手势绑定:

// 每个ListItem绑定长按和滑动手势组合

ListItem()

  .gesture(

    GestureGroup(

      GestureType.Sequence, 

      LongPressGesture({ repeat: true })

        .onActionStart(() => {

          // 触发拖拽起始动画(如缩放效果)

          animateTo({ duration: 100 }, () => this.dragItem = index);

        }),

      PanGesture()

        .onActionUpdate((event: GestureEvent) => {

          // 更新悬浮层位置(全屏范围)

          this.floatX = event.offsetX;

          this.floatY = event.offsetY;

        })

        .onActionEnd(() => {

          // 拖拽结束,更新数据源并恢复动画

          animateTo({ duration: 100 }, () => this.dragItem = -1);

        })

    )

  )

2/自定义悬浮层:使用绝对定位的<Stack>组件创建全屏悬浮层,通过状态变量控制拖拽项的实时位置

Stack() {

  List() {

    ForEach(this.dataArr, (item, index) => {

      ListItem(...) // 正常列表项

    })

  }

  // 全屏悬浮层(拖拽时显示)

  if (this.dragItem !== -1) {

    Image(item.icon)

      .position({ x: this.floatX, y: this.floatY })

      .zIndex(999) // 确保悬浮层在最上层

  }

}

在HarmonyOS Next中,实现全屏范围内拖拽排序可见的方法主要有:

  1. 使用DragEventDragController:通过DragController管理拖拽生命周期,结合DragEvent处理拖拽事件,可在全屏范围监听拖拽状态。

  2. Grid/List组件拖拽:利用GridList组件的onItemDragStartonItemDragEnter等回调,配合itemDrag属性实现拖拽排序,拖拽过程中元素在全屏可见。

  3. 自定义拖拽布局:通过@Drag装饰器标记可拖拽组件,使用onDragStartonDragMove等事件控制拖拽行为,结合全局事件监听实现全屏拖拽反馈。

这些方法均基于ArkUI框架,无需依赖Java或C语言。

在HarmonyOS Next中,要实现全屏范围内可见的拖拽排序,核心在于使用全局拖拽事件自定义预览图。List的onMove和Grid的拖拽排序默认的预览图受限于组件范围,若要在整个页面(全屏)显示拖拽预览,可以通过以下方法实现:

1. 使用DragEvent和自定义拖拽预览

通过监听组件的长按事件触发拖拽,并设置一个全屏显示的@Preview组件作为自定义拖拽预览视图。

关键步骤:

  • 在长按事件中,使用DragEvent发起拖拽,并通过setData传递数据。
  • 创建一个全屏覆盖的@Component作为预览组件,通过@Preview装饰器或动态显示控制其可见性。
  • 在拖拽过程中,根据拖拽位置更新预览组件的位置,实现全屏跟随效果。

示例代码片段:

// 自定义全屏预览组件
@Component
struct DragPreview {
  @State private left: number = 0
  @State private top: number = 0

  build() {
    // 使用绝对定位覆盖全屏
    Stack({ alignContent: Alignment.TopStart }) {
      // 预览内容
      Image($r('app.media.preview'))
        .position({ x: this.left, y: this.top })
    }
    .width('100%')
    .height('100%')
  }
}

// 在列表项中触发拖拽
ListItem() {
  // 列表项内容
}
.onTouch((event: TouchEvent) => {
  if (event.type === TouchType.LongPress) {
    // 触发拖拽,传递数据
    let dragEvent = event as DragEvent
    dragEvent.setData('itemData', this.item)
    // 显示全屏预览组件(可通过状态管理控制)
    showGlobalPreview()
  }
})

2. 结合@State管理预览状态

通过@State变量控制全屏预览组件的显示与隐藏,并在拖拽过程中实时更新其位置。

实现方式:

  • 在页面级别定义@State变量,如isDraggingpreviewPosition
  • 拖拽开始时,设置isDraggingtrue,显示全屏预览组件。
  • 监听拖拽移动事件,更新previewPosition,使预览图跟随手指移动。
  • 拖拽结束时,隐藏预览组件。

3. 使用Window管理全屏视图

通过Window模块创建悬浮窗或全屏透明窗口,作为拖拽预览的容器。这种方法更适用于复杂场景,但需要申请相应权限。

注意: 此方法涉及系统级窗口管理,需谨慎处理性能和权限问题。

总结

推荐优先使用**自定义预览组件结合DragEvent**的方案,通过状态控制实现全屏拖拽预览。这种方法无需额外权限,且能灵活控制预览样式和位置。Grid和List的默认拖拽排序功能可在此基础上扩展,通过自定义事件处理实现全屏预览效果。

回到顶部