鸿蒙5.0开发进阶:API ArkUI框架-ArkTS组件(拖拽事件)

鸿蒙5.0开发:ArkUI框架组件拖拽事件

往期鸿蒙全套实战文章必看:(文中附带全栈鸿蒙学习资料)


拖拽事件

拖拽事件指组件被长按后拖拽时触发的事件。

说明

从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。

应用本身预置的资源文件(即应用在安装前的HAP包中已经存在的资源文件)仅支持本地应用内拖拽。

ArkUI框架对以下组件实现了默认的拖拽能力,支持对数据的拖出或拖入响应,开发者只需要将这些组件的draggable属性设置为true,即可使用默认拖拽能力。其中,Text、TextInput、TextArea、Hyperlink、Image、RichEditor和Web组件的draggable属性默认为true。

开发者也可以通过实现通用拖拽事件来自定义拖拽响应。

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

onDragStart

onDragStart(event: (event: DragEvent, extraParams?: string) => CustomBuilder | DragItemInfo)

第一次拖拽此事件绑定的组件时,长按时间 >= 500ms,然后手指移动距离 >= 10vp,触发回调。

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

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

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

元服务API: 从API version 11开始,该接口支持在元服务中使用。

事件优先级: 长按触发时间 < 500ms,长按事件优先拖拽事件响应,长按触发时间 >= 500ms,拖拽事件优先长按事件响应。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
event(event: DragEvent, extraParams?: string) => CustomBuilder | DragItemInfo

回调函数。

说明:

event为拖拽事件信息。

extraParams为拖拽事件额外信息。需要解析为Json格式。

返回值:

类型说明
CustomBuilder | DragItemInfo

拽过程中显示的组件信息。

说明: 不支持全局builder。

onDragEnter

onDragEnter(event: (event: DragEvent, extraParams?: string) => void)

拖拽进入组件范围内时,触发回调,当监听了onDrop事件时,此事件才有效。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
event(event: DragEvent, extraParams?: string) => void

回调函数。

说明:

event为拖拽事件信息,包括拖拽点坐标。

extraParams为拖拽事件额外信息,需要解析为Json格式。

onDragMove

onDragMove(event: (event: DragEvent, extraParams?: string) => void)

拖拽在组件范围内移动时,触发回调,当监听了onDrop事件时,此事件才有效。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
event(event: DragEvent, extraParams?: string) => void

回调函数。

说明:

event为拖拽事件信息,包括拖拽点坐标。

extraParams为拖拽事件额外信息,需要解析为Json格式。

onDragLeave

onDragLeave(event: (event: DragEvent, extraParams?: string) => void)

拖拽离开组件范围内时,触发回调,当监听了onDrop事件时,此事件才有效。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
event(event: DragEvent, extraParams?: string) => void

回调函数。

说明:

event为拖拽事件信息,包括拖拽点坐标。

extraParams为拖拽事件额外信息,需要解析为Json格式。

onDrop

onDrop(event: (event: DragEvent, extraParams?: string) => void)

绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。如果开发者没有在onDrop中主动调用event.setResult()设置拖拽接收的结果,则系统按照数据接收成功处理。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
event(event: DragEvent, extraParams?: string) => void

回调函数。

说明:

event为拖拽事件信息,包括拖拽点坐标。

extraParams为拖拽事件额外信息,需要解析为Json格式。

onDragEnd

onDragEnd(event: (event: DragEvent, extraParams?: string) => void)

绑定此事件的组件触发的拖拽结束后,触发回调。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
event(event: DragEvent, extraParams?: string) => void

回调函数。

说明:

event为拖拽事件信息,不包括拖拽点坐标。

extraParams为拖拽事件额外信息,需要解析为Json格式。

onPreDrag12+

onPreDrag(event: (preDragStatus: PreDragStatus) => void)

绑定此事件的组件,当触发拖拽发起前的不同阶段时,触发回调。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
callbackCallback<(preDragStatus: PreDragStatus> ) => void回调函数。

DragItemInfo说明

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型必填描述
pixelMapPixelMap设置拖拽过程中显示的图片。
builderCustomBuilder

拖拽过程中显示自定义组件,如果设置了pixelMap,则忽略此值。

说明:

不支持全局builder。如果builder中使用了Image组件,应尽量开启同步加载,即配置Image的syncLoad为true。该builder只用于生成当次拖拽中显示的图片,builder的修改不会同步到当前正在拖拽的图片,对builder的修改需要在下一次拖拽时生效。

extraInfostring拖拽项的描述。

extraParams说明

用于返回组件在拖拽中需要用到的额外信息。

extraParams是Json对象转换的string字符串,可以通过Json.parse转换的Json对象获取如下属性。

名称类型描述
selectedIndexnumber

当拖拽事件设在父容器的子元素时,selectedIndex表示当前被拖拽子元素是父容器第selectedIndex个子元素,selectedIndex从0开始。

仅在ListItem组件的拖拽事件中生效。

insertIndexnumber

当前拖拽元素在List组件中放下时,insertIndex表示被拖拽元素插入该组件的第insertIndex个位置,insertIndex从0开始。

仅在List组件的拖拽事件中生效。

DragEvent

系统能力: SystemCapability.ArkUI.ArkUI.Full

属性

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型描述
useCustomDropAnimation10+boolean

当拖拽结束时,是否使能并使用系统默认落位动效。

应用可将该值设定为true来禁用系统默认落位动效,并实现自己的自定义落位动效。

当不配置或设置为false时,系统默认落位动效生效,当松手位置的控件可接收拖拽的数据时,落位为缩小消失动效,若不可接收数据,则为放大消失动效。

当未禁用系统默认落位动效情况下,应用不应再实现自定义动效,以避免动效上的冲突。

dragBehavior10+DragBehavior切换复制和剪贴模式的角标显示状态。

方法

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称返回值类型描述
setData(unifiedData: UnifiedData)10+void

向DragEvent中设置拖拽相关数据。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getData()10+UnifiedData

从DragEvent中获取拖拽相关数据。数据获取结果请参考错误码说明。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getSummary()10+Summary

从DragEvent中获取拖拽相关数据的简介。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

setResult(dragRect: DragResult)10+void

向DragEvent中设置拖拽结果。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getResult()10+DragResult

从DragEvent中获取拖拽结果。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getPreviewRect()10+Rectangle

获取拖拽跟手图相对于当前窗口的位置,以及跟手图尺寸信息,单位VP,其中x和y代表跟手图左上角的窗口坐标,width和height代表跟手图的尺寸。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getVelocityX()10+number

获取当前拖拽的x轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从左往右为正,反之为负。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getVelocityY()10+number获取当前拖拽的y轴方向拖动速度。坐标轴原点为屏幕左上角,单位为vp,分正负方向速度,从上往下为正,反之为负。
getVelocity()10+number

获取当前拖拽的主方向拖动速度。为xy轴方向速度的平方和的算术平方根。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getWindowX()10+number

当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getWindowY()10+number

当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getDisplayX()10+number

当前拖拽点相对于屏幕左上角的x轴坐标,单位为vp。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getDisplayY()10+number

当前拖拽点相对于屏幕左上角的y轴坐标,单位为vp。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

getX()(deprecated)number

当前拖拽点相对于窗口左上角的x轴坐标,单位为vp。

从API Version 10开始不再维护,建议使用getWindowX()代替。

getY()(deprecated)number

当前拖拽点相对于窗口左上角的y轴坐标,单位为vp。

从API Version 10开始不再维护,建议使用getWindowY()代替。

getModifierKeyState12+(Array<string>) => bool获取功能键按压状态。报错信息请参考以下错误码。支持功能键 'Ctrl'|'Alt'|'Shift'|'Fn',设备外接带Fn键的键盘不支持Fn键查询。

错误码:

以下错误码的详细介绍。

错误码ID错误信息
401Parameter error. Possible causes: 1. Incorrect parameter types. 2. Parameter verification failed.
190001Data not found.
190002Data error.

DragResult10+枚举说明

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称描述
DRAG_SUCCESSFUL拖拽成功,在onDrop中使用。
DRAG_FAILED拖拽失败,在onDrop中使用。
DRAG_CANCELED拖拽取消,在onDrop中使用。
DROP_ENABLED组件允许落入,在onDragMove中使用。
DROP_DISABLED组件不允许落入,在onDragMove中使用。

DragBehavior10+

当设置DragResult为DROP_ENABLED后,可设置DragBehavior为复制(copy)或剪切(move)。DragBehavior用来向开发者描述数据的处理方式是复制(copy)还是剪切(move),但无法最终决定对数据的实际处理方式。DragBehavior会通过onDragEnd带回给数据拖出方,发起拖拽的一方可通过DragBehavior来区分做出的是复制还是剪切数据的不同行为。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称描述
COPY指定对数据的处理方式为复制。
MOVE指定对数据的处理方式为剪切。

PreDragStatus12+枚举说明

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称描述
ACTION_DETECTING_STATUS0拖拽手势启动阶段。(按下50ms时触发)
READY_TO_TRIGGER_DRAG_ACTION1拖拽准备完成,可发起拖拽阶段。(按下500ms时触发)
PREVIEW_LIFT_STARTED2拖拽浮起动效发起阶段。(按下800ms时触发)
PREVIEW_LIFT_FINISHED3拖拽浮起动效结束阶段。(浮起动效完全结束时触发)
PREVIEW_LANDING_STARTED4拖拽落回动效发起阶段。(落回动效发起时触发)
PREVIEW_LANDING_FINISHED5拖拽落回动效结束阶段。(落回动效结束时触发)
ACTION_CANCELED_BEFORE_DRAG6拖拽浮起落位动效中断。(已满足READY_TO_TRIGGER_DRAG_ACTION状态后,未达到动效阶段,手指抬手时触发)

示例

该示例展示了部分组件(如Image和Text等)拖拽和可落入区域的设置。

// xxx.ets
import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct Index {
@State targetImage: string = '';
@State targetText: string = 'Drag Text';
@State imageWidth: number = 100;
@State imageHeight: number = 100;
@State imgState: Visibility = Visibility.Visible;
@State videoSrc: string = 'resource://RAWFILE/02.mp4';
@State abstractContent: string = "abstract";
@State textContent: string = "";
@State backGroundColor: Color = Color.Transparent;

@Builder
pixelMapBuilder() {
Column() {
Image($r('app.media.icon'))
.width(120)
.height(120)
.backgroundColor(Color.Yellow)
}
}

getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) {
try {
let data: UnifiedData = event.getData();
if (!data) {
return false;
}
let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords();
if (!records || records.length <= 0) {
return false;
}
callback(event);
return true;
} catch (e) {
console.log("getData failed, code = " + (e as BusinessError).code + ", message = " + (e as BusinessError).message);
return false;
}
}

getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) {
if (this.getDataFromUdmfRetry(event, callback)) {
return;
}
setTimeout(() => {
this.getDataFromUdmfRetry(event, callback);
}, 1500);
}

private PreDragChange(preDragStatus: PreDragStatus): void {
if (preDragStatus == PreDragStatus.READY_TO_TRIGGER_DRAG_ACTION) {
this.backGroundColor = Color.Red;
} else if (preDragStatus == PreDragStatus.ACTION_CANCELED_BEFORE_DRAG
|| preDragStatus == PreDragStatus.PREVIEW_LANDING_FINISHED) {
this.backGroundColor = Color.Blue;
}
}

build() {
Row() {
Column() {
Text('start Drag')
.fontSize(18)
.width('100%')
.height(40)
.margin(10)
.backgroundColor('#008888')
Image($r('app.media.icon'))
.width(100)
.height(100)
.draggable(true)
.margin({ left: 15 })
.visibility(this.imgState)
.onDragEnd((event) => {
// onDragEnd里取到的result值在接收方onDrop设置
if (event.getResult() === DragResult.DRAG_SUCCESSFUL) {
promptAction.showToast({ duration: 100, message: 'Drag Success' });
} else if (event.getResult() === DragResult.DRAG_FAILED) {
promptAction.showToast({ duration: 100, message: 'Drag failed' });
}
})
Text('test drag event')
.width('100%')
.height(100)
.draggable(true)
.margin({ left: 15 })
.copyOption(CopyOptions.InApp)
TextArea({ placeholder: 'please input words' })
.copyOption(CopyOptions.InApp)
.width('100%')
.height(50)
.draggable(true)
Search({ placeholder: 'please input you word' })
.searchButton('Search')
.width('100%')
.height(80)
.textFont({ size: 20 })
Column() {
Text('change video source')
}.draggable(true)
.onDragStart((event) => {
let video: unifiedDataChannel.Video = new unifiedDataChannel.Video();
video.videoUri = '/resources/rawfile/01.mp4';
let data: unifiedDataChannel.UnifiedData = new unifiedDataChannel.UnifiedData(video);
(event as DragEvent).setData(data);
return { builder: () => {
this.pixelMapBuilder()
}, extraInfo: 'extra info' };
})

Column() {
Text('this is abstract')
.fontSize(20)
.width('100%')
}.margin({ left: 40, top: 20 })
.width('100%')
.height(100)
.onDragStart((event) => {
this.backGroundColor = Color.Transparent;
let data: unifiedDataChannel.PlainText = new unifiedDataChannel.PlainText();
data.abstract = 'this is abstract';
data.textContent = 'this is content this is content';
(event as DragEvent).setData(new unifiedDataChannel.UnifiedData(data));
})
.onPreDrag((status: PreDragStatus) => {
this.PreDragChange(status);
})
.backgroundColor(this.backGroundColor)
}.width('45%')
.height('100%')

Column() {
Text('Drag Target Area')
.fontSize(20)
.width('100%')
.height(40)
.margin(10)
.backgroundColor('#008888')
Image(this.targetImage)
.width(this.imageWidth)
.height(this.imageHeight)
.draggable(true)
.margin({ left: 15 })
.border({ color: Color.Black, width: 1 })
.allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE])
.onDrop((dragEvent?: DragEvent) => {
this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
let rect: Rectangle = event.getPreviewRect();
this.imageWidth = Number(rect.width);
this.imageHeight = Number(rect.height);
this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri;
event.useCustomDropAnimation = false;
this.imgState = Visibility.None;
// 显式设置result为successful,则将该值传递给拖出方的onDragEnd
event.setResult(DragResult.DRAG_SUCCESSFUL);
})
})

Text(this.targetText)
.width('100%')
.height(100)
.border({ color: Color.Black, width: 1 })
.margin(15)
.allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT])
.onDrop((dragEvent?: DragEvent) => {
this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
this.targetText = plainText.textContent;
})
})

Video({ src: this.videoSrc, previewUri: $r('app.media.icon') })
.width('100%')
.height(200)
.controls(true)
.allowDrop([uniformTypeDescriptor.UniformDataType.VIDEO])

Column() {
Text(this.abstractContent).fontSize(20).width('100%')
Text(this.textContent).fontSize(15).width('100%')
}
.width('100%')
.height(100)
.margin(20)
.border({ color: Color.Black, width: 1 })
.allowDrop([uniformTypeDescriptor.UniformDataType.PLAIN_TEXT])
.onDrop((dragEvent?: DragEvent) => {
this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => {
let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords();
let plainText: unifiedDataChannel.PlainText = records[0] as unifiedDataChannel.PlainText;
this.abstractContent = plainText.abstract as string;
this.textContent = plainText.textContent;
})
})
}.width('45%')
.height('100%')
.margin({ left: '5%' })
}
.height('100%')
}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值