1e41f4b71Sopenharmony_ci# Drag Event 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciThe drag event, bolstered by the drag and drop framework, represents a mode of data transfer using a mouse device or gesture: Users can drag data from one component to another. The component from which data is dragged is the drag source; and the component to which data is dropped is the drop target. This drag and drop operation enables users to easily move, copy, or delete data. The following are some key concepts involved: 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci* Drag operation: an operation that begins when a user selects a draggable component, continues when the user drags the component on the screen, and ends when the user releases the component on a droppable component. 8e41f4b71Sopenharmony_ci* Drag preview (background): a visual representation of the data being dragged. You can set it by using [CustomerBuilder](../reference/apis-arkui/arkui-ts/ts-types.md#custombuilder8) or [DragItemInfo](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#dragiteminfo) of [onDragStart](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragstart), or by using the universal attribute [dragPreview](../reference/apis-arkui/arkui-ts/ts-universal-attributes-drag-drop.md#dragpreview11). 9e41f4b71Sopenharmony_ci* Drag data: data being dragged; encapsulated using the UDMF API [UnifiedData](../reference/apis-arkdata/js-apis-data-unifiedDataChannel.md#unifieddata). 10e41f4b71Sopenharmony_ci* Drag source: component that initiates the drag operation and provides data. 11e41f4b71Sopenharmony_ci* Drop target: component that can receive and process drag data. 12e41f4b71Sopenharmony_ci* Drag point: position where the mouse device or finger has in contact with the screen. It is used to determine whether data enters a drop target. 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci## Drag Process 15e41f4b71Sopenharmony_ci 16e41f4b71Sopenharmony_ci### Gesture-based Drag Operation 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ciIf a drag operation is initiated by a gesture, the framework checks whether the current component is draggable. For draggable components ([Search](../reference/apis-arkui/arkui-ts/ts-basic-components-search.md), [TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md), [TextArea](../reference/apis-arkui/arkui-ts/ts-basic-components-textarea.md), [RichEditor](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md), [Text](../reference/apis-arkui/arkui-ts/ts-basic-components-text.md), [Image](../reference/apis-arkui/arkui-ts/ts-basic-components-image.md), <!--Del-->[FormComponent](../reference/apis-arkui/arkui-ts/ts-basic-components-formcomponent-sys.md), <!--DelEnd-->[Hyperlink](../reference/apis-arkui/arkui-ts/ts-container-hyperlink.md)), the framework checks whether their [draggable](../reference/apis-arkui/arkui-ts/ts-universal-attributes-drag-drop.md#draggable) attribute is set to **true** (this attribute is true by default if layered parameters are used); for other components, the framework checks whether the **onDragStart** callback is set. If the attribute or callback is set as required, the framework starts dragging once a user has long pressed the component for 500 ms or longer, and displays a drag preview once the user has long pressed the component for 800 ms. 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ciBelow you can see the drag process initiated by a gesture (finger or stylus). 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci### Mouse-based Drag Operation 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ciWhen a mouse device is used as the pointer, the framework starts dragging once the draggable component has been moved with the left mouse button by more than 1 vp. 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ciA drag and drop can occur in a single application, or start in one application and end in another. The following callback events are provided for you to detect the dragging status and intervene in the default dragging behavior of the system. 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ci| Callback Event| Description| 31e41f4b71Sopenharmony_ci| ---------------- | ------------------------| 32e41f4b71Sopenharmony_ci| onDragStart | Triggered when a draggable component is dragged.<br>You can use this callback to detect the initiation of dragging behavior. You can also set the drag data and drag preview in this callback. To avoid extra performance overhead, it is recommended that the drag preview be returned in the mode of **pixelmap**, instead of **customBuilder**.| 33e41f4b71Sopenharmony_ci| onDragEnter | Triggered when a dragged item enters the boundaries of the component. This callback is called only when the component listens for the [onDrop](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondrop) event.| 34e41f4b71Sopenharmony_ci| onDragMove| Triggered when the dragged item moves in the boundaries of the component. This callback is called only when the component listens for the **onDrop** event.<br>During the movement, the **setResult** API in [DragEvent](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#dragevent) can be used to affect the system appearance in some scenarios.<br>1. Set **DragResult.DROP\_ENABLED**.<br>2. Set **DragResult.DROP\_DISABLED**.| 35e41f4b71Sopenharmony_ci| onDragLeave | Triggered when the dragged item leaves the boundaries of the component. This callback is called only when the component listens for the **onDrop** event.<br>By default, the **onDragLeave** callback is not called in the following cases:<br>1. An item in a parent component is dragged to one of its child components.<br>2. The layout of the drop target component overlaps that of the drag source component.<br>Since API version 12, the [setDragEventStrictReportingEnabled](../reference/apis-arkui/js-apis-arkui-UIContext.md#setdrageventstrictreportingenabled12) API in [UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md) can be used to trigger the **onDragLeave** event in a strict fashion.| 36e41f4b71Sopenharmony_ci| onDrop | Triggered when the dragged item is dropped on the component. The dragging result must be set in this callback through the **setResult** API in **DragEvent**. Otherwise, the **getResult** API in the **onDragEnd** method of the drag source component only returns the default result **DragResult.DRAG\_FAILED**.<br>This callback is where you can intervene in the default drop processing behavior. The system preferentially executes the **onDrop** callback and processes the drag data based on the **setResult** method in the callback function.<br>1. If **DragResult.DRAG\_SUCCESSFUL** is set, you need to process the data on your own; the system does not process the data.<br>2. If **DragResult.DRAG\_FAILED** is set, the system does not process the data.<br>3. If **DragResult.DRAG\_CANCELED** is set, the system does not process the data.<br>4. Setting **DragResult.DROP\_ENABLED** or **DragResult.DROP\_DISABLED** will be ignored, producing the same effect as **DragResult.DRAG\_FAILED**.| 37e41f4b71Sopenharmony_ci| onDragEnd | Triggered when dragging of the component ends.| 38e41f4b71Sopenharmony_ci| onPreDrag | Triggered when the component enters a state prior to a drop and drop operation.<br>You can use this callback to listen for the value of [PreDragStatus](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#predragstatus12) to prepare corresponding data.<br>1. **ACTION\_DETECTING\_STATUS**: A drag gesture is being detected. (Triggered when the component is long pressed for 50 ms.)<br>2. **READY\_TO\_TRIGGER\_DRAG\_ACTION**: The component is ready to be dragged. (Triggered when the component is long pressed for 500 ms.)<br>3. **PREVIEW\_LIFT\_STARTED**: A lift animation is started. (Triggered when the component is long pressed for 800 ms.)<br>4. **PREVIEW\_LIFT\_FINISHED**: A lift animation is finished. (Triggered at the completion of the lift animation.)<br>5. **PREVIEW\_LANDING\_STARTED**: A drop animation is started. (Triggered when the drop animation starts.)<br>6. **PREVIEW\_LANDING\_FINISHED**: A drop animation is finished. (Triggered when the drop animation ends.)<br>7. **ACTION\_CANCELED\_BEFORE\_DRAG**: A drop animation is terminated. (Triggered when the finger is lifted off the screen after the component enters the **READY\_TO\_TRIGGER\_DRAG\_ACTION** state.)| 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ciFor more usage, see [Drag Event](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md) 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci## Drag Preview 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ciThe drag preview is an image displayed during the drag and drop operation. It is a visual representation of the drag data, not the component itself. You can set it to any supported image that you want to display to users. The **customBuilder** or **pixelmap** object returned by the **onDragStart** callback can be used to set the drag preview – snapshot of the component by default – displayed during dragging and moving. The **customBuilder** or **pixelmap** object set by the **dragpreview** attribute can be used to set the drag preview – snapshot of the component by default – during a lift animation and dragging. 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ciYou can set the opacity, rounded corners, shadow, and blur for the drag preview. For details, see [Drag and Drop Control](../reference/apis-arkui/arkui-ts/ts-universal-attributes-drag-drop.md). 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci**Constraints**: 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ci* For a container component, if the internal content exceeds the range of the container component due to **position**, **offset**, and other settings, the component snapshot does not capture the content beyond the range. To show the out-of-range content, you can expand the container scope or customize the container. 51e41f4b71Sopenharmony_ci* Regardless of how the component snapshot is captured, using a custom builder or the default mode, the snapshot does not support the transform APIs, such as [scale](../reference/apis-arkui/arkui-ts/ts-universal-attributes-transformation.md#scale) and [rotate](../reference/apis-arkui/arkui-ts/ts-universal-attributes-transformation.md#rotate). 52e41f4b71Sopenharmony_ci 53e41f4b71Sopenharmony_ci## How to Develop 54e41f4b71Sopenharmony_ci 55e41f4b71Sopenharmony_ci### General Drag and Drop Adaptation 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ciThe following uses the [Image](../reference/apis-arkui/arkui-ts/ts-basic-components-image.md) component as an example to describe the basic procedure for drag and drop development and the precautions to be taken during development. 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci1. Make the component draggable. 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci* Set the **draggable** attribute to **true** and set the **onDragStart** callback function. In the callback function, you can use UDMF to set the drag data and return the custom drag preview. 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci ```ts 64e41f4b71Sopenharmony_ci import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ci Image($r('app.media.app_icon')) 67e41f4b71Sopenharmony_ci .width(100) 68e41f4b71Sopenharmony_ci .height(100) 69e41f4b71Sopenharmony_ci .draggable(true) 70e41f4b71Sopenharmony_ci .onDragStart((event) => { 71e41f4b71Sopenharmony_ci let data: unifiedDataChannel.Image = new unifiedDataChannel.Image(); 72e41f4b71Sopenharmony_ci data.imageUri = 'common/pic/img.png'; 73e41f4b71Sopenharmony_ci let unifiedData = new unifiedDataChannel.UnifiedData(data); 74e41f4b71Sopenharmony_ci event.setData(unifiedData); 75e41f4b71Sopenharmony_ci 76e41f4b71Sopenharmony_ci let dragItemInfo: DragItemInfo = { 77e41f4b71Sopenharmony_ci pixelMap: this.pixmap, 78e41f4b71Sopenharmony_ci extraInfo: "this is extraInfo", 79e41f4b71Sopenharmony_ci }; 80e41f4b71Sopenharmony_ci // The custom drag preview is returned in onDragStart. 81e41f4b71Sopenharmony_ci return dragItemInfo; 82e41f4b71Sopenharmony_ci }) 83e41f4b71Sopenharmony_ci ``` 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci* The gesture-based drag operation is initiated by a long press gesture bound at the underlying layer. If a long press gesture is also bound to the dragged component, gesture conflict will occur, resulting in dragging to fail. To avoid such an issue, you can use parallel gestures. 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci ```ts 88e41f4b71Sopenharmony_ci .parallelGesture(LongPressGesture().onAction(() => { 89e41f4b71Sopenharmony_ci promptAction.showToast({ duration: 100, message: 'Long press gesture trigger' }); 90e41f4b71Sopenharmony_ci })) 91e41f4b71Sopenharmony_ci ``` 92e41f4b71Sopenharmony_ci 93e41f4b71Sopenharmony_ci2. Customize the drag preview. 94e41f4b71Sopenharmony_ci 95e41f4b71Sopenharmony_ci * Prepare the pixel map for the custom drag preview within the callback triggered by [onPreDrag](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#onpredrag12) after a long press of 50 ms. 96e41f4b71Sopenharmony_ci 97e41f4b71Sopenharmony_ci ```ts 98e41f4b71Sopenharmony_ci .onPreDrag((status: PreDragStatus) => { 99e41f4b71Sopenharmony_ci if (preDragStatus == PreDragStatus.ACTION_DETECTING_STATUS) { 100e41f4b71Sopenharmony_ci this.getComponentSnapshot(); 101e41f4b71Sopenharmony_ci } 102e41f4b71Sopenharmony_ci }) 103e41f4b71Sopenharmony_ci ``` 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci * Generate the specific pixel map by calling [componentSnapshot.createFromBuilder](../reference/apis-arkui/js-apis-arkui-componentSnapshot.md#componentsnapshotcreatefrombuilder). 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci ```ts 108e41f4b71Sopenharmony_ci @Builder 109e41f4b71Sopenharmony_ci pixelMapBuilder() { 110e41f4b71Sopenharmony_ci Column() { 111e41f4b71Sopenharmony_ci Image($r('app.media.startIcon')) 112e41f4b71Sopenharmony_ci .width(120) 113e41f4b71Sopenharmony_ci .height(120) 114e41f4b71Sopenharmony_ci .backgroundColor(Color.Yellow) 115e41f4b71Sopenharmony_ci } 116e41f4b71Sopenharmony_ci } 117e41f4b71Sopenharmony_ci private getComponentSnapshot(): void { 118e41f4b71Sopenharmony_ci componentSnapshot.createFromBuilder(()=>{this.pixelMapBuilder()}, 119e41f4b71Sopenharmony_ci (error: Error, pixmap: image.PixelMap) => { 120e41f4b71Sopenharmony_ci if(error){ 121e41f4b71Sopenharmony_ci console.log("error: " + JSON.stringify(error)) 122e41f4b71Sopenharmony_ci return; 123e41f4b71Sopenharmony_ci } 124e41f4b71Sopenharmony_ci this.pixmap = pixmap; 125e41f4b71Sopenharmony_ci }) 126e41f4b71Sopenharmony_ci } 127e41f4b71Sopenharmony_ci ``` 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci3. To strictly execute the [onDragLeave](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragleave) event, use the [setDragEventStrictReportingEnabled](../reference/apis-arkui/js-apis-arkui-UIContext.md#setdrageventstrictreportingenabled12) API. 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci ```ts 132e41f4b71Sopenharmony_ci import { UIAbility } from '@kit.AbilityKit'; 133e41f4b71Sopenharmony_ci import { window, UIContext } from '@kit.ArkUI'; 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci export default class EntryAbility extends UIAbility { 136e41f4b71Sopenharmony_ci onWindowStageCreate(windowStage: window.WindowStage): void { 137e41f4b71Sopenharmony_ci windowStage.loadContent('pages/Index', (err, data) => { 138e41f4b71Sopenharmony_ci if (err.code) { 139e41f4b71Sopenharmony_ci return; 140e41f4b71Sopenharmony_ci } 141e41f4b71Sopenharmony_ci windowStage.getMainWindow((err, data) => { 142e41f4b71Sopenharmony_ci if (err.code) { 143e41f4b71Sopenharmony_ci return; 144e41f4b71Sopenharmony_ci } 145e41f4b71Sopenharmony_ci let windowClass: window.Window = data; 146e41f4b71Sopenharmony_ci let uiContext: UIContext = windowClass.getUIContext(); 147e41f4b71Sopenharmony_ci uiContext.getDragController().setDragEventStrictReportingEnabled(true); 148e41f4b71Sopenharmony_ci }); 149e41f4b71Sopenharmony_ci }); 150e41f4b71Sopenharmony_ci } 151e41f4b71Sopenharmony_ci } 152e41f4b71Sopenharmony_ci ``` 153e41f4b71Sopenharmony_ci 154e41f4b71Sopenharmony_ci4. Set the badge displayed during dragging. 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci* You can set [allowDrop](../reference/apis-arkui/arkui-ts/ts-universal-attributes-drag-drop.md#allowdrop) to define the allowed data types for dropping to affect the badge display. The COPY badge is displayed when the drag data matches the allowed data types, the FORBIDDEN badge when it does not, and the MOVE badge if **allowDrop** is not set. The following example allows only data of HYPERLINK and PLAIN_TEXT types defined in UnifiedData. 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci ```ts 159e41f4b71Sopenharmony_ci .allowDrop([uniformTypeDescriptor.UniformDataType.HYPERLINK, uniformTypeDescriptor.UniformDataType.PLAIN_TEXT]) 160e41f4b71Sopenharmony_ci ``` 161e41f4b71Sopenharmony_ci 162e41f4b71Sopenharmony_ci* If the **onDrop** callback is implemented, you can control the badge display by setting [DragResult](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#dragresult10) to **DROP\_ENABLED** in **onDragMove** and setting [DragBehavior](../reference/apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#dragbehavior10) to **COPY** or **MOVE**. The following code forces the badge to display **MOVE** during a drag operation: 163e41f4b71Sopenharmony_ci 164e41f4b71Sopenharmony_ci ```ts 165e41f4b71Sopenharmony_ci .onDragMove((event) => { 166e41f4b71Sopenharmony_ci event.setResult(DragResult.DROP_ENABLED); 167e41f4b71Sopenharmony_ci event.dragBehavior = DragBehavior.MOVE; 168e41f4b71Sopenharmony_ci }) 169e41f4b71Sopenharmony_ci ``` 170e41f4b71Sopenharmony_ci 171e41f4b71Sopenharmony_ci5. Receive drag data. 172e41f4b71Sopenharmony_ci 173e41f4b71Sopenharmony_ci* Set the **onDrop** callback to handle the drag data and determine the drag result. 174e41f4b71Sopenharmony_ci 175e41f4b71Sopenharmony_ci ```ts 176e41f4b71Sopenharmony_ci .onDrop((dragEvent?: DragEvent) => { 177e41f4b71Sopenharmony_ci // Obtain the drag data. 178e41f4b71Sopenharmony_ci this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => { 179e41f4b71Sopenharmony_ci let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords(); 180e41f4b71Sopenharmony_ci let rect: Rectangle = event.getPreviewRect(); 181e41f4b71Sopenharmony_ci this.imageWidth = Number(rect.width); 182e41f4b71Sopenharmony_ci this.imageHeight = Number(rect.height); 183e41f4b71Sopenharmony_ci this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri; 184e41f4b71Sopenharmony_ci this.imgState = Visibility.None; 185e41f4b71Sopenharmony_ci // Explicitly set the result to successful, and then pass this value to onDragEnd of the drag source. 186e41f4b71Sopenharmony_ci event.setResult(DragResult.DRAG_SUCCESSFUL); 187e41f4b71Sopenharmony_ci }) 188e41f4b71Sopenharmony_ci ``` 189e41f4b71Sopenharmony_ci 190e41f4b71Sopenharmony_ci* Data transfer is managed by UDMF, which may experience latency with large data volumes. Therefore, you are advised to implement a retry mechanism with a 1500 ms delay after the initial data acquisition fails. 191e41f4b71Sopenharmony_ci 192e41f4b71Sopenharmony_ci ```ts 193e41f4b71Sopenharmony_ci getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) { 194e41f4b71Sopenharmony_ci try { 195e41f4b71Sopenharmony_ci let data: UnifiedData = event.getData(); 196e41f4b71Sopenharmony_ci if (!data) { 197e41f4b71Sopenharmony_ci return false; 198e41f4b71Sopenharmony_ci } 199e41f4b71Sopenharmony_ci let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords(); 200e41f4b71Sopenharmony_ci if (!records || records.length <= 0) { 201e41f4b71Sopenharmony_ci return false; 202e41f4b71Sopenharmony_ci } 203e41f4b71Sopenharmony_ci callback(event); 204e41f4b71Sopenharmony_ci return true; 205e41f4b71Sopenharmony_ci } catch (e) { 206e41f4b71Sopenharmony_ci console.log("getData failed, code: " + (e as BusinessError).code + ", message: " + (e as BusinessError).message); 207e41f4b71Sopenharmony_ci return false; 208e41f4b71Sopenharmony_ci } 209e41f4b71Sopenharmony_ci } 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) { 212e41f4b71Sopenharmony_ci if (this.getDataFromUdmfRetry(event, callback)) { 213e41f4b71Sopenharmony_ci return; 214e41f4b71Sopenharmony_ci } 215e41f4b71Sopenharmony_ci setTimeout(() => { 216e41f4b71Sopenharmony_ci this.getDataFromUdmfRetry(event, callback); 217e41f4b71Sopenharmony_ci }, 1500); 218e41f4b71Sopenharmony_ci } 219e41f4b71Sopenharmony_ci ``` 220e41f4b71Sopenharmony_ci 221e41f4b71Sopenharmony_ci6. The drag initiator can detect the result of the drag operation by setting the **onDragEnd** callback. 222e41f4b71Sopenharmony_ci 223e41f4b71Sopenharmony_ci ```ts 224e41f4b71Sopenharmony_ci import { promptAction } from '@kit.ArkUI'; 225e41f4b71Sopenharmony_ci 226e41f4b71Sopenharmony_ci .onDragEnd((event) => { 227e41f4b71Sopenharmony_ci // The result value obtained from onDragEnd is set in onDrop of the drop target. 228e41f4b71Sopenharmony_ci if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { 229e41f4b71Sopenharmony_ci promptAction.showToast({ duration: 100, message: 'Drag Success' }); 230e41f4b71Sopenharmony_ci } else if (event.getResult() === DragResult.DRAG_FAILED) { 231e41f4b71Sopenharmony_ci promptAction.showToast({ duration: 100, message: 'Drag failed' }); 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci }) 234e41f4b71Sopenharmony_ci ``` 235e41f4b71Sopenharmony_ci 236e41f4b71Sopenharmony_ci### Multi-Select Drag and Drop Adaptation 237e41f4b71Sopenharmony_ci 238e41f4b71Sopenharmony_ciSince API version 12, the [Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md) and [List](../reference/apis-arkui/arkui-ts/ts-container-list.md) components, specifically the **GridItem** and **ListItem** components within them, support multi-select drag and drop, currently only accessible through the **onDragStart** API. The following uses **Grid** as an example to describe the basic procedure for multi-select drag and drop development and key considrations during development. 239e41f4b71Sopenharmony_ci 240e41f4b71Sopenharmony_ci1. Enable multi-select drag and drop. 241e41f4b71Sopenharmony_ci 242e41f4b71Sopenharmony_ci* Create **GridItem** child components and bind the **onDragStart** callback to them. In addition, set the **GridItem** components to be selectable. 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ci ```ts 245e41f4b71Sopenharmony_ci Grid() { 246e41f4b71Sopenharmony_ci ForEach(this.numbers, (idx: number) => { 247e41f4b71Sopenharmony_ci GridItem() { 248e41f4b71Sopenharmony_ci Column() 249e41f4b71Sopenharmony_ci .backgroundColor(this.colors[idx % 9]) 250e41f4b71Sopenharmony_ci .width(50) 251e41f4b71Sopenharmony_ci .height(50) 252e41f4b71Sopenharmony_ci .opacity(1.0) 253e41f4b71Sopenharmony_ci .id('grid'+idx) 254e41f4b71Sopenharmony_ci } 255e41f4b71Sopenharmony_ci .onDragStart(()=>{}) 256e41f4b71Sopenharmony_ci .selectable(true) 257e41f4b71Sopenharmony_ci }, (idx: string) => idx) 258e41f4b71Sopenharmony_ci } 259e41f4b71Sopenharmony_ci ``` 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ci* Multi-select drag and drop is disabled by default. To enable it, set **isMultiSelectionEnabled** to **true** in the **DragInteractionOptions** parameter of the [dragPreviewOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-drag-drop.md#dragpreviewoptions11) API. **DragInteractionOptions** also has the **defaultAnimationBeforeLifting** parameter, which, when set to **true**, applies a default scaling down animation as the lift animation for the component. 262e41f4b71Sopenharmony_ci 263e41f4b71Sopenharmony_ci ```ts 264e41f4b71Sopenharmony_ci .dragPreviewOptions({isMultiSelectionEnabled:true,defaultAnimationBeforeLifting:true}) 265e41f4b71Sopenharmony_ci ``` 266e41f4b71Sopenharmony_ci 267e41f4b71Sopenharmony_ci* To maintain the selected state, set the **selected** attribute of the **GridItem** child component to **true**. For example, use [onClick](../reference/apis-arkui/arkui-ts/ts-universal-events-click.md#onclick) to set a specific component to the selected state. 268e41f4b71Sopenharmony_ci 269e41f4b71Sopenharmony_ci ```ts 270e41f4b71Sopenharmony_ci .selected(this.isSelectedGrid[idx]) 271e41f4b71Sopenharmony_ci .onClick(()=>{ 272e41f4b71Sopenharmony_ci this.isSelectedGrid[idx] = !this.isSelectedGrid[idx] 273e41f4b71Sopenharmony_ci }) 274e41f4b71Sopenharmony_ci ``` 275e41f4b71Sopenharmony_ci 276e41f4b71Sopenharmony_ci2. Optimize the multi-select drag and drop performance. 277e41f4b71Sopenharmony_ci 278e41f4b71Sopenharmony_ci* In multi-select drag and drop scenarios, there is a clustering animation effect when multiple items are selected. This effect captures a snapshot of the selected components currently displayed on the screen, which can lead to high performance costs if there are too many selected components. To save on performance, multi-select drag and drop supports obtaining a snapshot from **dragPreview** to use as the basis for the clustering animation. 279e41f4b71Sopenharmony_ci 280e41f4b71Sopenharmony_ci ```ts 281e41f4b71Sopenharmony_ci .dragPreview({ 282e41f4b71Sopenharmony_ci pixelMap:this.pixmap 283e41f4b71Sopenharmony_ci }) 284e41f4b71Sopenharmony_ci ``` 285e41f4b71Sopenharmony_ci 286e41f4b71Sopenharmony_ci* You can obtain snapshots of a component by calling the **get** method of **componentSnapshot** when the component is selected. The following shows how to use the component ID to obtain the snapshot. 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci ```ts 289e41f4b71Sopenharmony_ci @State previewData: DragItemInfo[] = [] 290e41f4b71Sopenharmony_ci @State isSelectedGrid: boolean[] = [] 291e41f4b71Sopenharmony_ci .onClick(()=>{ 292e41f4b71Sopenharmony_ci this.isSelectedGrid[idx] = !this.isSelectedGrid[idx] 293e41f4b71Sopenharmony_ci if (this.isSelectedGrid[idx]) { 294e41f4b71Sopenharmony_ci let gridItemName = 'grid' + idx 295e41f4b71Sopenharmony_ci componentSnapshot.get(gridItemName, (error: Error, pixmap: image.PixelMap)=>{ 296e41f4b71Sopenharmony_ci this.pixmap = pixmap 297e41f4b71Sopenharmony_ci this.previewData[idx] = { 298e41f4b71Sopenharmony_ci pixelMap:this.pixmap 299e41f4b71Sopenharmony_ci } 300e41f4b71Sopenharmony_ci }) 301e41f4b71Sopenharmony_ci } 302e41f4b71Sopenharmony_ci }) 303e41f4b71Sopenharmony_ci ``` 304e41f4b71Sopenharmony_ci 305e41f4b71Sopenharmony_ci3. Set the multi-select display effects. 306e41f4b71Sopenharmony_ci 307e41f4b71Sopenharmony_ci Use **stateStyles** to set display effects for selected and unselected states for easy distinction. 308e41f4b71Sopenharmony_ci 309e41f4b71Sopenharmony_ci ```ts 310e41f4b71Sopenharmony_ci @Styles 311e41f4b71Sopenharmony_ci normalStyles(): void{ 312e41f4b71Sopenharmony_ci .opacity(1.0) 313e41f4b71Sopenharmony_ci } 314e41f4b71Sopenharmony_ci 315e41f4b71Sopenharmony_ci @Styles 316e41f4b71Sopenharmony_ci selectStyles(): void{ 317e41f4b71Sopenharmony_ci .opacity(0.4) 318e41f4b71Sopenharmony_ci } 319e41f4b71Sopenharmony_ci 320e41f4b71Sopenharmony_ci .stateStyles({ 321e41f4b71Sopenharmony_ci normal : this.normalStyles, 322e41f4b71Sopenharmony_ci selected: this.selectStyles 323e41f4b71Sopenharmony_ci }) 324e41f4b71Sopenharmony_ci ``` 325e41f4b71Sopenharmony_ci 326e41f4b71Sopenharmony_ci4. Adapt the number badge. 327e41f4b71Sopenharmony_ci 328e41f4b71Sopenharmony_ci Configure the number badge for multi-select drag and drop using the **numberBadge** parameter in **dragPreviewOptions**, adjusting it based on the number of selected items. 329e41f4b71Sopenharmony_ci 330e41f4b71Sopenharmony_ci ```ts 331e41f4b71Sopenharmony_ci @State numberBadge: number = 0; 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci .onClick(()=>{ 334e41f4b71Sopenharmony_ci this.isSelectedGrid[idx] = !this.isSelectedGrid[idx] 335e41f4b71Sopenharmony_ci if (this.isSelectedGrid[idx]) { 336e41f4b71Sopenharmony_ci this.numberBadge++; 337e41f4b71Sopenharmony_ci } else { 338e41f4b71Sopenharmony_ci this.numberBadge--; 339e41f4b71Sopenharmony_ci } 340e41f4b71Sopenharmony_ci }) 341e41f4b71Sopenharmony_ci // Set the numberBadge parameter in dragPreviewOptions for the number badge in multi-select scenarios. 342e41f4b71Sopenharmony_ci .dragPreviewOptions({numberBadge: this.numberBadge}) 343e41f4b71Sopenharmony_ci ``` 344e41f4b71Sopenharmony_ci 345e41f4b71Sopenharmony_ci## Example 346e41f4b71Sopenharmony_ci 347e41f4b71Sopenharmony_ci### General Drag and Drop Adaptation Case 348e41f4b71Sopenharmony_ci 349e41f4b71Sopenharmony_ci```ts 350e41f4b71Sopenharmony_ciimport { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; 351e41f4b71Sopenharmony_ciimport { promptAction, componentSnapshot } from '@kit.ArkUI'; 352e41f4b71Sopenharmony_ciimport { BusinessError } from '@kit.BasicServicesKit'; 353e41f4b71Sopenharmony_ciimport { image } from '@kit.ImageKit'; 354e41f4b71Sopenharmony_ci 355e41f4b71Sopenharmony_ci@Entry 356e41f4b71Sopenharmony_ci@Component 357e41f4b71Sopenharmony_cistruct Index { 358e41f4b71Sopenharmony_ci @State targetImage: string = ''; 359e41f4b71Sopenharmony_ci @State imageWidth: number = 100; 360e41f4b71Sopenharmony_ci @State imageHeight: number = 100; 361e41f4b71Sopenharmony_ci @State imgState: Visibility = Visibility.Visible; 362e41f4b71Sopenharmony_ci @State pixmap: image.PixelMap|undefined = undefined 363e41f4b71Sopenharmony_ci 364e41f4b71Sopenharmony_ci @Builder 365e41f4b71Sopenharmony_ci pixelMapBuilder() { 366e41f4b71Sopenharmony_ci Column() { 367e41f4b71Sopenharmony_ci Image($r('app.media.startIcon')) 368e41f4b71Sopenharmony_ci .width(120) 369e41f4b71Sopenharmony_ci .height(120) 370e41f4b71Sopenharmony_ci .backgroundColor(Color.Yellow) 371e41f4b71Sopenharmony_ci } 372e41f4b71Sopenharmony_ci } 373e41f4b71Sopenharmony_ci 374e41f4b71Sopenharmony_ci getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) { 375e41f4b71Sopenharmony_ci try { 376e41f4b71Sopenharmony_ci let data: UnifiedData = event.getData(); 377e41f4b71Sopenharmony_ci if (!data) { 378e41f4b71Sopenharmony_ci return false; 379e41f4b71Sopenharmony_ci } 380e41f4b71Sopenharmony_ci let records: Array<unifiedDataChannel.UnifiedRecord> = data.getRecords(); 381e41f4b71Sopenharmony_ci if (!records || records.length <= 0) { 382e41f4b71Sopenharmony_ci return false; 383e41f4b71Sopenharmony_ci } 384e41f4b71Sopenharmony_ci callback(event); 385e41f4b71Sopenharmony_ci return true; 386e41f4b71Sopenharmony_ci } catch (e) { 387e41f4b71Sopenharmony_ci console.log("getData failed, code: " + (e as BusinessError).code + ", message: " + (e as BusinessError).message); 388e41f4b71Sopenharmony_ci return false; 389e41f4b71Sopenharmony_ci } 390e41f4b71Sopenharmony_ci } 391e41f4b71Sopenharmony_ci // Obtain UDMF data with a retry mechanism of 1500 ms if the initial attempt fails. 392e41f4b71Sopenharmony_ci getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) { 393e41f4b71Sopenharmony_ci if (this.getDataFromUdmfRetry(event, callback)) { 394e41f4b71Sopenharmony_ci return; 395e41f4b71Sopenharmony_ci } 396e41f4b71Sopenharmony_ci setTimeout(() => { 397e41f4b71Sopenharmony_ci this.getDataFromUdmfRetry(event, callback); 398e41f4b71Sopenharmony_ci }, 1500); 399e41f4b71Sopenharmony_ci } 400e41f4b71Sopenharmony_ci // Use the createFromBuilder API of componentSnapshot to capture a snapshot of a custom builder. 401e41f4b71Sopenharmony_ci private getComponentSnapshot(): void { 402e41f4b71Sopenharmony_ci componentSnapshot.createFromBuilder(()=>{this.pixelMapBuilder()}, 403e41f4b71Sopenharmony_ci (error: Error, pixmap: image.PixelMap) => { 404e41f4b71Sopenharmony_ci if(error){ 405e41f4b71Sopenharmony_ci console.log("error: " + JSON.stringify(error)) 406e41f4b71Sopenharmony_ci return; 407e41f4b71Sopenharmony_ci } 408e41f4b71Sopenharmony_ci this.pixmap = pixmap; 409e41f4b71Sopenharmony_ci }) 410e41f4b71Sopenharmony_ci } 411e41f4b71Sopenharmony_ci // Prepare a custom screenshot pixel map after a 50 ms long press is detected. 412e41f4b71Sopenharmony_ci private PreDragChange(preDragStatus: PreDragStatus): void { 413e41f4b71Sopenharmony_ci if (preDragStatus == PreDragStatus.ACTION_DETECTING_STATUS) { 414e41f4b71Sopenharmony_ci this.getComponentSnapshot(); 415e41f4b71Sopenharmony_ci } 416e41f4b71Sopenharmony_ci } 417e41f4b71Sopenharmony_ci 418e41f4b71Sopenharmony_ci build() { 419e41f4b71Sopenharmony_ci Row() { 420e41f4b71Sopenharmony_ci Column() { 421e41f4b71Sopenharmony_ci Text('start Drag') 422e41f4b71Sopenharmony_ci .fontSize(18) 423e41f4b71Sopenharmony_ci .width('100%') 424e41f4b71Sopenharmony_ci .height(40) 425e41f4b71Sopenharmony_ci .margin(10) 426e41f4b71Sopenharmony_ci .backgroundColor('#008888') 427e41f4b71Sopenharmony_ci Row() { 428e41f4b71Sopenharmony_ci Image($r('app.media.app_icon')) 429e41f4b71Sopenharmony_ci .width(100) 430e41f4b71Sopenharmony_ci .height(100) 431e41f4b71Sopenharmony_ci .draggable(true) 432e41f4b71Sopenharmony_ci .margin({ left: 15 }) 433e41f4b71Sopenharmony_ci .visibility(this.imgState) 434e41f4b71Sopenharmony_ci // Bind a parallel gesture to trigger a custom long press gesture. 435e41f4b71Sopenharmony_ci .parallelGesture(LongPressGesture().onAction(() => { 436e41f4b71Sopenharmony_ci promptAction.showToast({ duration: 100, message: 'Long press gesture trigger' }); 437e41f4b71Sopenharmony_ci })) 438e41f4b71Sopenharmony_ci .onDragStart((event) => { 439e41f4b71Sopenharmony_ci let data: unifiedDataChannel.Image = new unifiedDataChannel.Image(); 440e41f4b71Sopenharmony_ci data.imageUri = 'common/pic/img.png'; 441e41f4b71Sopenharmony_ci let unifiedData = new unifiedDataChannel.UnifiedData(data); 442e41f4b71Sopenharmony_ci event.setData(unifiedData); 443e41f4b71Sopenharmony_ci 444e41f4b71Sopenharmony_ci let dragItemInfo: DragItemInfo = { 445e41f4b71Sopenharmony_ci pixelMap: this.pixmap, 446e41f4b71Sopenharmony_ci extraInfo: "this is extraInfo", 447e41f4b71Sopenharmony_ci }; 448e41f4b71Sopenharmony_ci return dragItemInfo; 449e41f4b71Sopenharmony_ci }) 450e41f4b71Sopenharmony_ci // Prepare a custom drag preview in advance. 451e41f4b71Sopenharmony_ci .onPreDrag((status: PreDragStatus) => { 452e41f4b71Sopenharmony_ci this.PreDragChange(status); 453e41f4b71Sopenharmony_ci }) 454e41f4b71Sopenharmony_ci .onDragEnd((event) => { 455e41f4b71Sopenharmony_ci // The result value obtained from onDragEnd is set in onDrop of the drop target. 456e41f4b71Sopenharmony_ci if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { 457e41f4b71Sopenharmony_ci promptAction.showToast({ duration: 100, message: 'Drag Success' }); 458e41f4b71Sopenharmony_ci } else if (event.getResult() === DragResult.DRAG_FAILED) { 459e41f4b71Sopenharmony_ci promptAction.showToast({ duration: 100, message: 'Drag failed' }); 460e41f4b71Sopenharmony_ci } 461e41f4b71Sopenharmony_ci }) 462e41f4b71Sopenharmony_ci } 463e41f4b71Sopenharmony_ci 464e41f4b71Sopenharmony_ci Text('Drag Target Area') 465e41f4b71Sopenharmony_ci .fontSize(20) 466e41f4b71Sopenharmony_ci .width('100%') 467e41f4b71Sopenharmony_ci .height(40) 468e41f4b71Sopenharmony_ci .margin(10) 469e41f4b71Sopenharmony_ci .backgroundColor('#008888') 470e41f4b71Sopenharmony_ci Row() { 471e41f4b71Sopenharmony_ci Image(this.targetImage) 472e41f4b71Sopenharmony_ci .width(this.imageWidth) 473e41f4b71Sopenharmony_ci .height(this.imageHeight) 474e41f4b71Sopenharmony_ci .draggable(true) 475e41f4b71Sopenharmony_ci .margin({ left: 15 }) 476e41f4b71Sopenharmony_ci .border({ color: Color.Black, width: 1 }) 477e41f4b71Sopenharmony_ci // Set the drag behavior to MOVE, which means no badge is displayed. 478e41f4b71Sopenharmony_ci .onDragMove((event) => { 479e41f4b71Sopenharmony_ci event.setResult(DragResult.DROP_ENABLED) 480e41f4b71Sopenharmony_ci event.dragBehavior = DragBehavior.MOVE 481e41f4b71Sopenharmony_ci }) 482e41f4b71Sopenharmony_ci .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) 483e41f4b71Sopenharmony_ci .onDrop((dragEvent?: DragEvent) => { 484e41f4b71Sopenharmony_ci // Obtain the drag data. 485e41f4b71Sopenharmony_ci this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => { 486e41f4b71Sopenharmony_ci let records: Array<unifiedDataChannel.UnifiedRecord> = event.getData().getRecords(); 487e41f4b71Sopenharmony_ci let rect: Rectangle = event.getPreviewRect(); 488e41f4b71Sopenharmony_ci this.imageWidth = Number(rect.width); 489e41f4b71Sopenharmony_ci this.imageHeight = Number(rect.height); 490e41f4b71Sopenharmony_ci this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri; 491e41f4b71Sopenharmony_ci this.imgState = Visibility.None; 492e41f4b71Sopenharmony_ci // Explicitly set the result to successful, and then pass this value to onDragEnd of the drag source. 493e41f4b71Sopenharmony_ci event.setResult(DragResult.DRAG_SUCCESSFUL); 494e41f4b71Sopenharmony_ci }) 495e41f4b71Sopenharmony_ci }) 496e41f4b71Sopenharmony_ci } 497e41f4b71Sopenharmony_ci } 498e41f4b71Sopenharmony_ci .width('100%') 499e41f4b71Sopenharmony_ci .height('100%') 500e41f4b71Sopenharmony_ci } 501e41f4b71Sopenharmony_ci .height('100%') 502e41f4b71Sopenharmony_ci } 503e41f4b71Sopenharmony_ci} 504e41f4b71Sopenharmony_ci 505e41f4b71Sopenharmony_ci``` 506e41f4b71Sopenharmony_ci 507e41f4b71Sopenharmony_ci### Multi-Select Drag and Drop Adaptation Case 508e41f4b71Sopenharmony_ci 509e41f4b71Sopenharmony_ci```ts 510e41f4b71Sopenharmony_ciimport { componentSnapshot } from '@kit.ArkUI'; 511e41f4b71Sopenharmony_ciimport { image } from '@kit.ImageKit'; 512e41f4b71Sopenharmony_ci 513e41f4b71Sopenharmony_ci@Entry 514e41f4b71Sopenharmony_ci@Component 515e41f4b71Sopenharmony_cistruct GridEts { 516e41f4b71Sopenharmony_ci @State pixmap: image.PixelMap|undefined = undefined 517e41f4b71Sopenharmony_ci @State numbers: number[] = [] 518e41f4b71Sopenharmony_ci @State isSelectedGrid: boolean[] = [] 519e41f4b71Sopenharmony_ci @State previewData: DragItemInfo[] = [] 520e41f4b71Sopenharmony_ci @State colors: Color[] = [Color.Red, Color.Blue, Color.Brown, Color.Gray, Color.Green, Color.Grey, Color.Orange,Color.Pink ,Color.Yellow] 521e41f4b71Sopenharmony_ci @State numberBadge: number = 0; 522e41f4b71Sopenharmony_ci 523e41f4b71Sopenharmony_ci @Styles 524e41f4b71Sopenharmony_ci normalStyles(): void{ 525e41f4b71Sopenharmony_ci .opacity(1.0) 526e41f4b71Sopenharmony_ci } 527e41f4b71Sopenharmony_ci 528e41f4b71Sopenharmony_ci @Styles 529e41f4b71Sopenharmony_ci selectStyles(): void{ 530e41f4b71Sopenharmony_ci .opacity(0.4) 531e41f4b71Sopenharmony_ci } 532e41f4b71Sopenharmony_ci 533e41f4b71Sopenharmony_ci onPageShow(): void { 534e41f4b71Sopenharmony_ci let i: number = 0 535e41f4b71Sopenharmony_ci for(i=0;i<100;i++){ 536e41f4b71Sopenharmony_ci this.numbers.push(i) 537e41f4b71Sopenharmony_ci this.isSelectedGrid.push(false) 538e41f4b71Sopenharmony_ci this.previewData.push({}) 539e41f4b71Sopenharmony_ci } 540e41f4b71Sopenharmony_ci } 541e41f4b71Sopenharmony_ci 542e41f4b71Sopenharmony_ci @Builder 543e41f4b71Sopenharmony_ci RandomBuilder(idx: number) { 544e41f4b71Sopenharmony_ci Column() 545e41f4b71Sopenharmony_ci .backgroundColor(this.colors[idx % 9]) 546e41f4b71Sopenharmony_ci .width(50) 547e41f4b71Sopenharmony_ci .height(50) 548e41f4b71Sopenharmony_ci .opacity(1.0) 549e41f4b71Sopenharmony_ci } 550e41f4b71Sopenharmony_ci 551e41f4b71Sopenharmony_ci build() { 552e41f4b71Sopenharmony_ci Column({ space: 5 }) { 553e41f4b71Sopenharmony_ci Grid() { 554e41f4b71Sopenharmony_ci ForEach(this.numbers, (idx: number) => { 555e41f4b71Sopenharmony_ci GridItem() { 556e41f4b71Sopenharmony_ci Column() 557e41f4b71Sopenharmony_ci .backgroundColor(this.colors[idx % 9]) 558e41f4b71Sopenharmony_ci .width(50) 559e41f4b71Sopenharmony_ci .height(50) 560e41f4b71Sopenharmony_ci .opacity(1.0) 561e41f4b71Sopenharmony_ci .id('grid'+idx) 562e41f4b71Sopenharmony_ci } 563e41f4b71Sopenharmony_ci .dragPreview(this.previewData[idx]) 564e41f4b71Sopenharmony_ci .selectable(true) 565e41f4b71Sopenharmony_ci .selected(this.isSelectedGrid[idx]) 566e41f4b71Sopenharmony_ci // Set the multi-select display effects. 567e41f4b71Sopenharmony_ci .stateStyles({ 568e41f4b71Sopenharmony_ci normal : this.normalStyles, 569e41f4b71Sopenharmony_ci selected: this.selectStyles 570e41f4b71Sopenharmony_ci }) 571e41f4b71Sopenharmony_ci .onClick(()=>{ 572e41f4b71Sopenharmony_ci this.isSelectedGrid[idx] = !this.isSelectedGrid[idx] 573e41f4b71Sopenharmony_ci if (this.isSelectedGrid[idx]) { 574e41f4b71Sopenharmony_ci this.numberBadge++; 575e41f4b71Sopenharmony_ci let gridItemName = 'grid' + idx 576e41f4b71Sopenharmony_ci // Call the get API in componentSnapshot to obtain the component snapshot pixel map on selection. 577e41f4b71Sopenharmony_ci componentSnapshot.get(gridItemName, (error: Error, pixmap: image.PixelMap)=>{ 578e41f4b71Sopenharmony_ci this.pixmap = pixmap 579e41f4b71Sopenharmony_ci this.previewData[idx] = { 580e41f4b71Sopenharmony_ci pixelMap:this.pixmap 581e41f4b71Sopenharmony_ci } 582e41f4b71Sopenharmony_ci }) 583e41f4b71Sopenharmony_ci } else { 584e41f4b71Sopenharmony_ci this.numberBadge--; 585e41f4b71Sopenharmony_ci } 586e41f4b71Sopenharmony_ci }) 587e41f4b71Sopenharmony_ci // Enable multiselect and set the number badge. 588e41f4b71Sopenharmony_ci .dragPreviewOptions({numberBadge: this.numberBadge},{isMultiSelectionEnabled:true,defaultAnimationBeforeLifting:true}) 589e41f4b71Sopenharmony_ci .onDragStart(()=>{ 590e41f4b71Sopenharmony_ci }) 591e41f4b71Sopenharmony_ci }, (idx: string) => idx) 592e41f4b71Sopenharmony_ci } 593e41f4b71Sopenharmony_ci .columnsTemplate('1fr 1fr 1fr 1fr 1fr') 594e41f4b71Sopenharmony_ci .columnsGap(5) 595e41f4b71Sopenharmony_ci .rowsGap(10) 596e41f4b71Sopenharmony_ci .backgroundColor(0xFAEEE0) 597e41f4b71Sopenharmony_ci }.width('100%').margin({ top: 5 }) 598e41f4b71Sopenharmony_ci } 599e41f4b71Sopenharmony_ci} 600e41f4b71Sopenharmony_ci``` 601