# @ohos.arkui.dragController (DragController)
The **dragController** module provides APIs for initiating drag actions. When receiving a gesture event, such as a touch or long-press event, an application can initiate a drag action and carry drag information therein.
> **NOTE**
>
> The initial APIs of this module are supported since API version 10. Newly added APIs will be marked with a superscript to indicate their earliest API version.
> The functionality of this module depends on UI context. This means that the APIs of this module cannot be used where the UI context is unclear. For details, see [UIContext](./js-apis-arkui-UIContext.md#uicontext).
> Since API version 10, you can use the [getDragController](./js-apis-arkui-UIContext.md#getdragcontroller11) API in **UIContext** to obtain the **DragController** object associated with the current UI context.
> You can preview how this component looks on a real device, but not in DevEco Studio Previewer.
## Modules to Import
```ts
import dragController from "@ohos.arkui.dragController";
```
## dragController.executeDrag
executeDrag(custom: CustomBuilder | DragItemInfo, dragInfo: DragInfo, callback: AsyncCallback< {event: DragEvent, extraParams: string}>): void
Initiates a drag action, with the object to be dragged and the drag information passed in. This API uses an asynchronous callback to return the result.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------------------------------------------------------ | ---- | -------------------------------- |
| custom | [CustomBuilder](../arkui-ts/ts-types.md#custombuilder8) \| [DragItemInfo](../arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo) | Yes | Object to be dragged.
**NOTE**
The global builder is not supported. If the [\](../arkui-ts/ts-basic-components-image.md) component is used in the builder, enable synchronous loading, that is, set the [syncLoad](../arkui-ts/ts-basic-components-image.md#attributes) attribute of the component to **true**.|
| dragInfo | [DragInfo](#draginfo) | Yes | Drag information. |
| callback | [AsyncCallback](./js-apis-base.md#asynccallback)<{event: [DragEvent](../arkui-ts/ts-universal-events-drag-drop.md#dragevent), extraParams: string}> | Yes | Callback used to return the result.
- **event**: drag event information that includes only the drag result.
- **extraParams**: extra information about the drag event. |
**Error codes**
| ID| Error Message |
| -------- | ------------- |
| 401 | if the parameters checking failed. |
| 100001 | if some internal handling failed. |
**Example**
```ts
import dragController from "@ohos.arkui.dragController"
import UDC from '@ohos.data.unifiedDataChannel';
@Entry
@Component
struct DragControllerPage {
@Builder DraggingBuilder() {
Column() {
Text("DraggingBuilder")
}
.width(100)
.height(100)
.backgroundColor(Color.Blue)
}
build() {
Column() {
Button('touch to execute drag')
.onTouch((event?:TouchEvent) => {
if(event){
if (event.type == TouchType.Down) {
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
class tmp{
event:DragEvent|undefined = undefined
extraParams:string = ''
}
let eve:tmp = new tmp()
dragController.executeDrag(()=>{this.DraggingBuilder()}, dragInfo, (err, eve) => {
if(eve.event){
if (eve.event.getResult() == DragResult.DRAG_SUCCESSFUL) {
// ...
} else if (eve.event.getResult() == DragResult.DRAG_FAILED) {
// ...
}
}
})
}
}
})
}
}
}
```
## dragController.executeDrag
executeDrag(custom: CustomBuilder | DragItemInfo, dragInfo: DragInfo): Promise<{event: DragEvent, extraParams: string}>
Initiates a drag action, with the object to be dragged and the drag information passed in. This API uses a promise to return the result.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------------------------------------------------------ | ---- | -------------------------------- |
| custom | [CustomBuilder](../arkui-ts/ts-types.md#custombuilder8) \| [DragItemInfo](../arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo) | Yes | Object to be dragged.|
| dragInfo | [DragInfo](#draginfo) | Yes | Drag information. |
**Return value**
| Type | Description |
| ------------------------------------------------------ | ------------------ |
| Promise<{event: [DragEvent](../arkui-ts/ts-universal-events-drag-drop.md#dragevent), extraParams: string}> | Promise used to return the result.
- **event**: drag event information that includes only the drag result.
- **extraParams**: extra information about the drag event.|
**Error codes**
| ID| Error Message |
| -------- | ------------- |
| 401 | if the parameters checking failed. |
| 100001 | if some internal handling failed. |
**Example**
```ts
import dragController from "@ohos.arkui.dragController"
import componentSnapshot from '@ohos.arkui.componentSnapshot';
import image from '@ohos.multimedia.image';
import UDC from '@ohos.data.unifiedDataChannel';
@Entry
@Component
struct DragControllerPage {
@State pixmap: image.PixelMap|null = null
@Builder DraggingBuilder() {
Column() {
Text("DraggingBuilder")
}
.width(100)
.height(100)
.backgroundColor(Color.Blue)
}
@Builder PixmapBuilder() {
Column() {
Text("PixmapBuilder")
}
.width(100)
.height(100)
.backgroundColor(Color.Blue)
}
build() {
Column() {
Button('touch to execute drag')
.onTouch((event?:TouchEvent) => {
if(event){
if (event.type == TouchType.Down) {
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
let pb:CustomBuilder = ():void=>{this.PixmapBuilder()}
componentSnapshot.createFromBuilder(pb).then((pix: image.PixelMap) => {
this.pixmap = pix;
let dragItemInfo: DragItemInfo = {
pixelMap: this.pixmap,
builder: ()=>{this.DraggingBuilder()},
extraInfo: "DragItemInfoTest"
}
class tmp{
event:DragResult|undefined = undefined
extraParams:string = ''
}
let eve:tmp = new tmp()
dragController.executeDrag(dragItemInfo, dragInfo)
.then((eve) => {
if (eve.event.getResult() == DragResult.DRAG_SUCCESSFUL) {
// ...
} else if (eve.event.getResult() == DragResult.DRAG_FAILED) {
// ...
}
})
.catch((err:Error) => {
})
})
}
}
})
}
.width('100%')
.height('100%')
}
}
```
## DragInfo
**System capability**: SystemCapability.ArkUI.ArkUI.Full
Defines the attributes required for initiating a drag action and information carried in the dragging process.
| Name | Type | Mandatory| Description |
| ----------- | ------------------------------------------------------ | ---- | ---------------------------------------- |
| pointerId | number | Yes | ID of the touch point on the screen when dragging is started. |
| data | [unifiedDataChannel.UnifiedData](js-apis-data-unifiedDataChannel.md#unifieddata) | No | Data carried in the dragging process. |
| extraParams | string | No | Additional information about the drag action. Not supported currently.|
| touchPoint11+ | [TouchPoint](../arkui-ts/ts-types.md#touchpoint11) | No | Coordinates of the touch point. If this parameter is not set, the touch point is centered. |
| previewOptions11+| [DragPreviewOptions](../arkui-ts/ts-universal-attributes-drag-drop.md#dragpreviewoptions11) | No | Custom configuration of the drag preview.|
## DragStatus11+
**System capability**: SystemCapability.ArkUI.ArkUI.Full
Describes the dragging start and end states.
| Name | Value | Description |
| ----------- | ------------------------------------------------------| ---------------------------------------- |
| STARTED | 0 | Dragging is started. |
| ENDED | 1 | Dragging ends. |
## DragAndDropInfo11+
**System capability**: SystemCapability.ArkUI.ArkUI.Full
Provides the data reported when the state changes during dragging.
| Name | Type | Mandatory| Description |
| ----------- | ------------------------------------------------------ | ---- | ---------------------------------------- |
| status | [DragStatus](#dragstatus11) | Yes | Current dragging state (started or ended). |
| event | [DragEvent](../arkui-ts/ts-universal-events-drag-drop.md#dragevent) | No | Drag event corresponding to the current state. |
| extraParams| string | No | Additional information about the drag action. Not supported currently.|
## DragAction11+
Implements a **DragAction** object to subscribe to drag state changes and start the drag service.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
### startDrag11+
startDrag(): Promise<void>
Starts the drag service. This API uses a promise to return the result.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Error codes**
| ID| Error Message |
| -------- | ------------- |
| 100001 | if some internal handling failed. |
**Example**
```ts
import dragController from "@ohos.arkui.dragController"
import UDC from '@ohos.data.unifiedDataChannel';
let customBuilders:Array = new Array();
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
try{
let dragAction: dragController.DragAction | null = dragController.createDragAction(customBuilders, dragInfo);
if(!dragAction){
console.log("listener dragAction is null");
return
}
dragAction.startDrag().then(()=>{}).catch((err:Error)=>{
console.log("start drag Error:" + err.message);
})
}catch(err) {
console.log("create dragAction Error:" + err.message);
}
```
### on('statusChange')11+
on(type: 'statusChange', callback: Callback<[DragAndDropInfo](#draganddropinfo11)>): void
Subscribes to drag state changes.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory | Description |
| ------ | ------ | ------- | ---------------- |
| type | string | Yes | Event type. The value is fixed at **'statusChange'**, which indicates the drag state change event.|
| callback | Callback<[DragAndDropInfo](#draganddropinfo11)> | Yes | Callback used to return a [DragAndDropInfo](#draganddropinfo11) instance.|
**Example**
```ts
import dragController from "@ohos.arkui.dragController"
import UDC from '@ohos.data.unifiedDataChannel';
let customBuilders:Array = new Array();
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
try{
let dragAction: dragController.DragAction | null = dragController.createDragAction(customBuilders, dragInfo);
if(!dragAction){
console.log("listener dragAction is null");
return
}
dragAction.on('statusChange', (dragAndDropInfo: dragController.DragAndDropInfo)=>{
console.info("Register to listen on drag status", JSON.stringify(dragAndDropInfo));
})
}catch(err) {
console.log("create dragAction Error:" + err.message);
}
```
### off('statusChange')11+
off(type: 'statusChange', callback?: Callback<[DragAndDropInfo](#draganddropinfo11)>): void
Unsubscribes from drag state changes.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory | Description |
| ------ | ------ | ------- | ---------------- |
| type | string | Yes | Event type. The value is fixed at **'statusChange'**, which indicates the drag state change event.|
| callback | Callback<[DragAndDropInfo](#draganddropinfo11)> | No | Callback used to return a [DragAndDropInfo](#draganddropinfo11) instance. If this parameter is not set, this API unsubscribes from all callbacks corresponding to **type**.|
**Example**
```ts
import dragController from "@ohos.arkui.dragController"
import UDC from '@ohos.data.unifiedDataChannel';
let customBuilders:Array = new Array();
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
try{
let dragAction: dragController.DragAction | null = dragController.createDragAction(customBuilders, dragInfo);
if(!dragAction){
console.log("listener dragAction is null");
return
}
dragAction.off('statusChange', (dragAndDropInfo: dragController.DragAndDropInfo)=>{
console.info("Cancel listening on drag status", JSON.stringify(dragAndDropInfo));
})
}catch(err) {
console.log("create dragAction Error:" + err.message);
}
```
## dragController.createDragAction11+
createDragAction(customArray: Array<CustomBuilder \| DragItemInfo>, dragInfo: DragInfo): DragAction
Creates a **DragAction** object, by explicitly specifying one or more drag previews, drag data, and information about the dragged object. If the drag initiated by a **DragAction** object is not complete, no new **DragAction** object can be created, and calling this API will throw an exception.
**NOTE**
You are advised to control the number of drag previews. If too many previews are passed in, the drag efficiency may be affected.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | ------------------------------------------------------------ | ---- | -------------------------------- |
| customArray | Array<[CustomBuilder](../arkui-ts/ts-types.md#custombuilder8) \| [DragItemInfo](../arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo)> | Yes | Object to be dragged.|
| dragInfo | [DragInfo](#draginfo) | Yes | Drag information. |
**Return value**
| Type | Description |
| ------------------------------------------------------ | ------------------ |
| [DragAction](#dragaction11)| **DragAction** object, which is used to subscribe to drag state changes and start the drag service.|
**Error codes**
| ID| Error Message |
| -------- | ------------- |
| 401 | Invalid input parameter |
| 100001 | If some internal handling failed |
**Example**
```ts
import dragController from "@ohos.arkui.dragController"
import componentSnapshot from '@ohos.arkui.componentSnapshot';
import image from '@ohos.multimedia.image';
import UDC from '@ohos.data.unifiedDataChannel';
@Entry
@Component
struct DragControllerPage {
@State pixmap: image.PixelMap | null = null
private dragAction: dragController.DragAction | null = null;
customBuilders:Array = new Array();
@Builder DraggingBuilder() {
Column() {
Text("DraggingBuilder")
}
.width(100)
.height(100)
.backgroundColor(Color.Blue)
}
build() {
Column() {
Column() {
Text ("Test")
}
.width(100)
.height(100)
.backgroundColor(Color.Red)
Button('Drag Multiple Objects').onTouch((event?:TouchEvent) => {
if(event){
if (event.type == TouchType.Down) {
console.log("muti drag Down by listener");
this.customBuilders.splice(0, this.customBuilders.length);
this.customBuilders.push(()=>{this.DraggingBuilder()});
this.customBuilders.push(()=>{this.DraggingBuilder()});
this.customBuilders.push(()=>{this.DraggingBuilder()});
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
try{
this.dragAction = dragController.createDragAction(this.customBuilders, dragInfo)
if(!this.dragAction){
console.log("listener dragAction is null");
return
}
this.dragAction.on('statusChange', (dragAndDropInfo: dragController.DragAndDropInfo)=>{
if (dragAndDropInfo.status == dragController.DragStatus.STARTED) {
console.log("drag has start");
} else if (dragAndDropInfo.status == dragController.DragStatus.ENDED){
console.log("drag has end");
if (!this.dragAction) {
return
}
this.dragAction.off('statusChange')
}
})
this.dragAction.startDrag().then(()=>{}).catch((err:Error)=>{
console.log("start drag Error:" + err.message);
})
} catch(err) {
console.log("create dragAction Error:" + err.message);
}
}
}
}).margin({top:20})
}
}
}
```
## AnimationOptions11+
**System capability**: SystemCapability.ArkUI.ArkUI.Full
Defines the attributes required for initiating a drag action and information carried in the dragging process.
| Name | Type | Mandatory| Description |
| ----------- | ------------------------------------------------------ | ---- | ---------------------------------------- |
| duration | number | No | Animation duration, in ms.
Default value: **1000**
**NOTE**
- If this parameter is set to a value less than 0, the value **0** is used.
- Floating-point values will be rounded down to integers. For example, if the value set is 1.2, **1** will be used.|
| curve | [Curve](../arkui-ts/ts-appendix-enums.md#curve) \| [ICurve](../apis/js-apis-curve.md#icurve) | No | Animation curve.
Default value: **Curve.EaseInOut**| |
## dragController.getDragPreview11+
getDragPreview(): DragPreview
Obtains the **DragPreview** object, which represents the preview displayed during a drag.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Return value**
| Type | Description |
| ------------| ------------------------------------------------|
| DragPreview | **DragPreview** object. It provides the API for setting the preview style. It does not work in the **OnDrop** and **OnDragEnd** callbacks.|
**Example**
For details, see [animate](#animate11).
## DragPreview11+
Implements a **DragPreview** object. This API does not work in the **OnDrop** and **OnDragEnd** callbacks.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
### setForegroundColor11+
setForegroundColor(color: ResourceColor): void
Sets the mask color of the drag preview. This API does not work in the **OnDrop** and **OnDragEnd** callbacks.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | -------------------------------- | ---- | ------------------------ |
| color | [ResourceColor](../arkui-ts/ts-types.md#resourcecolor) | Yes | Mask color of the drag preview. |
**Example**
For details, see [animate](#animate11).
### animate11+
animate(options: AnimationOptions, handler: () => void): void
Applies an animation to the background mask color changes. This API does not work in the **OnDrop** and **OnDragEnd** callbacks.
**System capability**: SystemCapability.ArkUI.ArkUI.Full
**Parameters**
| Name | Type | Mandatory| Description |
| -------- | -------------------------------- | ---- | -----------------------------------|
| options | [AnimationOptions](#animationoptions11) | Yes | Animation settings. |
| handler | () => void | Yes | Callback used to change attributes such as the background mask color. |
**Example**
1. In the **EntryAbility.ets** file, obtain the UI context and save it to LocalStorage.
```ts
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
import { UIContext } from '@ohos.arkui.UIContext';
let uiContext: UIContext;
let localStorage: LocalStorage = new LocalStorage('uiContext');
export default class EntryAbility extends UIAbility {
storage: LocalStorage = localStorage;
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
windowStage.getMainWindow((err, data) => {
if (err.code) {
hilog.error(0x0000, 'Failed to abtain the main window. Cause:' + err.message, '');
return;
}
let windowClass: window.Window = data;
uiContext = windowClass.getUIContext();
this.storage.setOrCreate('uiContext', uiContext);
})
});
}
}
```
2. In the **Index.ets** file, call **LocalStorage.getShared()** to obtain the UI context and then use the **DragController** object obtained to perform subsequent operations.
```ts
import UDC from '@ohos.data.unifiedDataChannel';
import hilog from '@ohos.hilog';
import dragController from "@ohos.arkui.dragController";
import image from '@ohos.multimedia.image';
import curves from '@ohos.curves';
import { BusinessError } from '@ohos.base';
import { UIContext } from '@ohos.arkui.UIContext';
let storages = LocalStorage.getShared();
@Entry(storages)
@Component
struct DragControllerPage {
@State pixmap: image.PixelMap|null = null
@Builder DraggingBuilder() {
Column() {
Text("DraggingBuilder")
}
.width(100)
.height(100)
.backgroundColor(Color.Blue)
}
@Builder PixmapBuilder() {
Column() {
Text("PixmapBuilder")
}
.width(100)
.height(100)
.backgroundColor(Color.Blue)
}
build() {
Column() {
Button('Drag Here').onDragEnter(() => {
try {
let uiContext: UIContext = storages.get('uiContext') as UIContext;
let previewObj: dragController.DragPreview = uiContext.getDragController().getDragPreview();
let foregroundColor: ResourceColor = Color.Green;
let previewAnimation: dragController.AnimationOptions = {
curve: curves.cubicBezierCurve(0.2,0,0,1),
}
previewObj.animate(previewAnimation, () => {
previewObj.setForegroundColor(foregroundColor);
});
} catch (error) {
let msg = (error as BusinessError).message;
let code = (error as BusinessError).code;
hilog.error(0x0000, `show error code is ${code}, message is ${msg}`, '');
}
})
.onDrop(() => {
})
Button ('Drag').onTouch ((event?:TouchEvent) => {
if(event){
if (event.type == TouchType.Down) {
let text = new UDC.Text()
let unifiedData = new UDC.UnifiedData(text)
let dragInfo: dragController.DragInfo = {
pointerId: 0,
data: unifiedData,
extraParams: ''
}
class tmp{
event:DragEvent|undefined = undefined
extraParams:string = ''
}
let eve:tmp = new tmp()
dragController.executeDrag(() => {
this.DraggingBuilder()
}, dragInfo, (err , eve) => {
hilog.info(0x0000, `ljx ${JSON.stringify(err)}`, '')
if (eve && eve.event) {
if (eve.event.getResult() == DragResult.DRAG_SUCCESSFUL) {
hilog.info(0x0000, 'success', '');
} else if (eve.event.getResult() == DragResult.DRAG_FAILED) {
hilog.info(0x0000, 'failed', '');
}
}
})
}
}
}).margin({top:100})
}
.width('100%')
.height('100%')
}
}