鸿蒙开发之拖拽事件

一、拖拽涉及的方法

Text(this.message)
    .fontSize(50)
    .fontWeight(FontWeight.Bold)
    //拖拽开始
    .onDragStart((event: DragEvent) => {
      console.log('drag event onDragStart'+event.getX())
    })
    //拖拽进入组件范围,需要监听onDrop配合
    .onDragEnter((event: DragEvent) => {
      console.log('drag event onDragEnter'+event.getX())

    })
    //拖拽在组件范围内移动,需要监听onDrop配合
    .onDragMove((event: DragEvent) => {
      console.log('drag event onDragMove'+event.getX())

    })
    //拖拽离开组件范围,需要监听onDrop配合
    .onDragLeave((event: DragEvent) => {
      console.log('drag event onDragLeave'+event.getX())

    })
    //拖拽结束时触发
     .onDrop((event: DragEvent) => {
      console.log('drag event onDrop'+event.getX())

    })

需要特别注意的是:拖拽触发时间是长按150ms。如果组件上有长按手势,需要看长按手势设置的触发时间。当长按手势配置时间小于等于150ms时,长按手势优先触发,如果长按手势设置的时间大于150ms,那么拖拽事件优先触发。

二、Demo示例

@Observed
class DragItem{
  title: string
  //是否在拖动中
  isDrag: boolean

  constructor(title: string, isDrag: boolean) {
    this.title = title
    this.isDrag = isDrag
  }
}

@Extend(Text) function dragItemTextStyle() {
  .fontColor(Color.White)
  .fontSize(40)
  .borderRadius(20)
  .borderWidth(3)
  .textAlign(TextAlign.Center)
  .width('25%')
  .height(55)
}

@Entry
@Component
struct OfficialDragPage {
  //记录拖动的index
  @State dragIndex: number = 0
  @State dataArray: Array<DragItem> = [
    new DragItem('A',false),
    new DragItem('B',false),
    new DragItem('C',false)
  ]

  build() {
      Column() {
        List({space:20}) {
          ForEach(this.dataArray,(item: DragItem,index) => {
            ListItem() {
              Column() {
                Childitem({item:this.dataArray[index]})
              }
              .onTouch((touch: TouchEvent) => {
                  if (touch.type == TouchType.Down) {
                    this.dragIndex = index
                    item.isDrag = true
                  }
                })
            }
          })
        }
        .listDirection(Axis.Horizontal)
        .onDrop((event,extraParam: string) => {
          let jsonStr = JSON.parse(extraParam)
          this.dataArray[this.dragIndex].isDrag = false
          this.changeData(this.dragIndex,jsonStr.insertIndex)
        })
        .padding({top:20})
      }
      .width('100%')
      .height('100%')
  }

  changeData(fromIndex:number,toIndex:number) {
    [this.dataArray[fromIndex], this.dataArray[toIndex]] = [this.dataArray[toIndex], this.dataArray[fromIndex]]
  }
}

@Component
struct Childitem {

  @ObjectLink item: DragItem

  @Builder pixelMapBuilder() {
    Column() {
      Text(this.item.title)
        .width('40%')
        .height(60)
        .fontSize(46)
        .borderRadius(10)
        .textAlign(TextAlign.Center)
        .backgroundColor(Color.Yellow)
    }
  }

  build() {
    Column() {
      Text(this.item.title)
        .backgroundColor( Color.Blue)
        .dragItemTextStyle()
        .visibility(this.item.isDrag ? Visibility.None : Visibility.Visible)
        .onDragStart(() => {
          return this.pixelMapBuilder()
        })

      Text()
        .dragItemTextStyle()
        .border({ width: 5, color: 'red' })
        .visibility(!this.item.isDrag ? Visibility.None : Visibility.Visible)
    }
  }
}

### 鸿蒙开发实现鼠标拖动窗口功能 在鸿蒙(HarmonyOS NEXT)开发中,通过 ArkTS 和 ArkUI 组件可以实现复杂的交互逻辑,其中包括鼠标拖动窗口的功能。以下是关于如何实现这一功能的具体说明。 #### 1. 拖拽事件的基础原理 在 HarmonyOS 中,拖拽操作通常依赖于 `onDragStart` 回调函数以及组件的 `draggable` 属性设置。对于某些特定组件(如 `Text`, `Image` 等),如果未显式禁用 `draggable` 属性,默认情况下可能支持拖拽行为[^3]。然而,窗口级别的拖动涉及更复杂的状态管理与布局调整。 #### 2. 实现步骤概述 为了实现鼠标拖动窗口的功能,开发者需要关注以下几个方面: - **绑定拖拽事件**:为窗口顶部栏或其他指定区域绑定拖拽事件监听器。 - **状态更新机制**:记录鼠标的初始位置和当前移动距离,动态计算并更新窗口的位置。 - **性能优化**:减少不必要的重绘操作,确保流畅体验。 #### 3. 示例代码 以下是一个简单的示例代码片段,展示如何利用 ArkTS 实现基本的鼠标拖动窗口效果: ```typescript @Entry @Component struct DraggableWindow { private startX: number = 0; private startY: number = 0; private offsetX: number = 0; private offsetY: number = 0; build() { Column({ space: 10 }) { Row() { // 可拖动的标题栏 Text('Drag Me') .fontSize(20) .fontColor(Color.White) .backgroundColor(Color.Blue) .width('100%') .height(50) .draggingPosition((x, y) => { this.startX = x; this.startY = y; }) .onTouch({ onStart(e) { this.offsetX = e.touches[0].screenX - this.startX; this.offsetY = e.touches[0].screenY - this.startY; }, onMove(e) { let newX = e.touches[0].screenX - this.offsetX; let newY = e.touches[0].screenY - this.offsetY; this.startX = Math.max(newX, 0); this.startY = Math.max(newY, 0); } }); } Rectangle() .fill(Color.Gray) .size({ width: '100%', height: 200 }) }.position({ top: this.startY, left: this.startX }).padding(10) } } ``` 此代码定义了一个可拖动的窗口结构,其中: - 使用 `onTouch` 方法捕获触摸事件,并实时更新窗口位置。 - 利用 `startX`, `startY` 记录初始坐标;`offsetX`, `offsetY` 存储偏移量。 #### 4. 关键点解析 - **拖拽范围限制**:可以通过条件语句控制窗口的最大边界,防止超出屏幕显示范围。 - **多端适配**:考虑到不同设备上的分辨率差异,建议采用相对单位(如百分比)替代固定像素值。 - **用户体验改进**:增加视觉反馈(例如阴影变化或透明度渐变),提升交互友好性。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值