DEV Community

Cover image for Dragging event
liu yang
liu yang

Posted on

Dragging event

Universal Drag and Drop Adaptation

Basic Steps and Considerations for Component Drag and Drop Development

Enabling Component Drag and Drop

  1. Set draggable Property: Set the draggable property to true and configure the onDragStart callback function. In the callback, you can use the Unified Data Management Framework (UDMF) to set the drag data and return a custom drag background image.
import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';

Image($r('app.media.app_icon'))
    .width(100)
    .height(100)
    .draggable(true)
    .onDragStart((event) => {
        let data: unifiedDataChannel.Image = new unifiedDataChannel.Image();
        data.imageUri = 'common/pic/img.png';
        let unifiedData = new unifiedDataChannel.UnifiedData(data);
        event.setData(unifiedData);

        let dragItemInfo: DragItemInfo = {
            pixelMap: this.pixmap,
            extraInfo: "this is extraInfo",
        };
        // Return custom drag background image in onDragStart callback
        return dragItemInfo;
    })
Enter fullscreen mode Exit fullscreen mode

Handling Long Press Gesture Conflicts

If you bind a long press gesture to a draggable component, it may conflict with the underlying long press gesture, causing the drag operation to fail. To resolve this, you can use parallel gestures.

.parallelGesture(LongPressGesture().onAction(() => {
    promptAction.showToast({ duration: 100, message: 'Long press gesture trigger' });
}))
Enter fullscreen mode Exit fullscreen mode

Customizing Drag Background Image

You can prepare a custom drag background image by setting the onPreDrag callback function, which is triggered 50ms after a long press.

.onPreDrag((status: PreDragStatus) => {
    if (status == PreDragStatus.ACTION_DETECTING_STATUS) {
        this.getComponentSnapshot();
    }
})
Enter fullscreen mode Exit fullscreen mode

The pixmap can be generated using the componentSnapshot.createFromBuilder function.

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

private getComponentSnapshot(): void {
    this.getUIContext().getComponentSnapshot().createFromBuilder(() => { this.pixelMapBuilder() },
    (error: Error, pixmap: image.PixelMap) => {
        if (error) {
            console.log("error: " + JSON.stringify(error));
            return;
        }
        this.pixmap = pixmap;
    })
}
Enter fullscreen mode Exit fullscreen mode

Ensuring onDragLeave Event

To ensure the onDragLeave event is triggered, you need to set setDragEventStrictReportingEnabled.

import { UIAbility } from '@kit.AbilityKit';
import { window, UIContext } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
    onWindowStageCreate(windowStage: window.WindowStage): void {
        windowStage.loadContent('pages/Index', (err, data) => {
            if (err.code) {
                return;
            }
            windowStage.getMainWindow((err, data) => {
                if (err.code) {
                    return;
                }
                let windowClass: window.Window = data;
                let uiContext: UIContext = windowClass.getUIContext();
                uiContext.getDragController().setDragEventStrictReportingEnabled(true);
            });
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

Drag and Drop Process with Badge Style

Define the accepted data types using allowDrop, which affects the badge display. When the dragged data matches the allowed types, a "COPY" badge is shown. If the data type is not allowed, a "FORBIDDEN" badge is shown. If allowDrop is not set, a "MOVE" badge is shown.

.allowDrop([uniformTypeDescriptor.UniformDataType.HYPERLINK, uniformTypeDescriptor.UniformDataType.PLAIN_TEXT])
Enter fullscreen mode Exit fullscreen mode

In the onDragMove callback, you can set DragResult to DROP_ENABLED and DragBehavior to COPY or MOVE to control the badge display.

.onDragMove((event) => {
    event.setResult(DragResult.DROP_ENABLED);
    event.dragBehavior = DragBehavior.MOVE;
})
Enter fullscreen mode Exit fullscreen mode

Receiving Dragged Data

Set the onDrop callback function to handle the dragged data and set the drag result.

.onDrop((dragEvent?: DragEvent) => {
    // Get dragged data
    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;
        this.imgState = Visibility.None;
        // Explicitly set result to successful, which will be passed to the onDragEnd of the drag source
        event.setResult(DragResult.DRAG_SUCCESSFUL);
    })
})
Enter fullscreen mode Exit fullscreen mode

Top comments (0)