Universal Drag and Drop Adaptation
Basic Steps and Considerations for Component Drag and Drop Development
Enabling Component Drag and Drop
-
Set draggable Property: Set the
draggable
property totrue
and configure theonDragStart
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;
})
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' });
}))
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();
}
})
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;
})
}
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);
});
});
}
}
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])
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;
})
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);
})
})
Top comments (0)