harmony 鸿蒙Drag Event
Drag Event
The ArkUI framework provides a set of drag event APIs to help you implement drag-and-drop functionality.These events include NODE_ON_PRE_DRAG, NODE_ON_DRAG_START, NODE_ON_DROP, NODE_ON_DRAG_ENTER, NODE_ON_DRAG_MOVE, NODE_ON_DRAG_LEAVE, and NODE_ON_DRAG_END. These events are triggered at different stages of the drag operation, allowing you to perform specific actions and manage the drag interaction as needed.
Basic Drag Implementation
In ArkUI, you can implement the drag-and-drop functionality using C and C++ by calling C APIs. The following provides step-by-step instructions using the Image component as an example, along with key points to keep in mind during development.
- Set a component draggable.
Obtain the Node-API, which you’ll need for node operations, such as creating a node.
```cpp
ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
```
Create an Image node and set the draggable and other related attributes.
```cpp
auto image = nodeAPI->createNode(ARKUI_NODE_IMAGE);
ArkUI_NumberValue NODE_IMAGE_SRC_Item = {.string = "/pages/common/1111.png"};
ArkUI_NumberValue imageWidthValue[] = {100};
ArkUI_AttributeItem imageWidthItem = {imageWidthValue, 1};
ArkUI_NumberValue imageHeightValue[] = {100};
ArkUI_AttributeItem imageHeightItem = {imageHeightValue, 1};
ArkUI_NumberValue marginValue[] = {20};
ArkUI_AttributeItem marginItem = {marginValue, 1};
nodeAPI->setAttribute(image, NODE_WIDTH, &imageWidthItem);
nodeAPI->setAttribute(image, NODE_HEIGHT, &imageHeightItem);
nodeAPI->setAttribute(image, NODE_IMAGE_SRC, &NODE_IMAGE_SRC_Item);
nodeAPI->setAttribute(image, NODE_MARGIN, &marginItem);
nodeAPI->registerNodeEvent(image, NODE_ON_DRAG_START, 1, nullptr);
auto returnValue1 = OH_ArkUI_SetNodeDraggable(image, true);
```
- Customize the drag preview and background image.
Create a PixelMap object and set its width, height, and other properties. Set dragPreviewOption for the Image node to customize the rounded corners and badges of the drag preview.
```cpp
// Create a PixelMap.
uint8_t data[960000];
size_t dataSize = 960000;
for (int i = 0; i < dataSize; i++) {
data[i] = i + 1;
}
// Create a parameter structure instance and set parameters.
OH_Pixelmap_InitializationOptions *createOpts;
OH_PixelmapInitializationOptions_Create(&createOpts);
OH_PixelmapInitializationOptions_SetWidth(createOpts, 400);
OH_PixelmapInitializationOptions_SetHeight(createOpts, 600);
OH_PixelmapInitializationOptions_SetPixelFormat(createOpts, PIXEL_FORMAT_BGRA_8888);
OH_PixelmapInitializationOptions_SetAlphaType(createOpts, PIXELMAP_ALPHA_TYPE_UNKNOWN);
// Create a Pixelmap instance.
OH_PixelmapNative *pixelmap = nullptr;
OH_PixelmapNative_CreatePixelmap(data, dataSize, createOpts, &pixelmap);
OH_PixelmapNative_Rotate(pixelmap, 45);
OH_PixelmapNative_Opcity(pixelmap, 0.1);
OH_PixelmapNative_Scale(pixelmap, 0.5, 1.0);
OH_PixelmapNative_Translate(pixelmap, 50.0, 10.0);
OH_ArkUI_SetNodeDragPreview(image, pixelmap);
auto *previewOptions = OH_ArkUI_CreateDragPreviewOption();
auto returnValue2 = OH_ArkUI_DragPreviewOption_SetNumberBadgeEnabled(previewOptions, true);
auto returnValue3 = OH_ArkUI_DragPreviewOption_SetBadgeNumber(previewOptions, 10);
auto returnValue4 = OH_ArkUI_DragPreviewOption_SetDefaultRadiusEnabled(previewOptions, true);
OH_ArkUI_SetNodeDragPreviewOption(image, previewOptions);
```
- Set related events.
Use a unified callback to handle events. Distinguish between different events using eventType.
```cpp
nodeAPI->registerNodeEventReceiver([](ArkUI_NodeEvent *event) {
auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
auto targetId = OH_ArkUI_NodeEvent_GetTargetId(event);
auto *dragEvent = OH_ArkUI_NodeEvent_GetDragEvent(event);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"targetId=%{public}d,eventType=%{public}d,", targetId,
eventType);
switch (eventType) {
case NODE_ON_CLICK: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"ARKUI_NODE_BUTTON click! dragable");
break;
}
case NODE_ON_PRE_DRAG: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "NODE_ON_PRE_DRAG EventReceiver");
break;
}
case NODE_ON_DRAG_START: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"NODE_ON_DRAG_START EventReceiver");
break;
}
case NODE_ON_DROP: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "NODE_ON_DROP EventReceiver");
break;
}
case NODE_ON_DRAG_ENTER: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"NODE_ON_DRAG_ENTER EventReceiver");
break;
}
case NODE_ON_DRAG_MOVE: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"NODE_ON_DRAG_MOVE EventReceiver");
break;
}
case NODE_ON_DRAG_LEAVE: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"NODE_ON_DRAG_LEAVE EventReceiver");
break;
}
case NODE_ON_DRAG_END: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "NODE_ON_DRAG_END EventReceiver");
break;
}
}
});
```
- Handle the NODE_ON_DRAG_START event.
In the NODE_ON_DRAG_START event, perform operations required to initiate the drag operation, typically involving data processing. For example, create a UdmfRecord, add the required data (such as imageUri) to the UdmfRecord in the fileUri type, set the UdmfRecord to udmfData, and set udmfData to DragEvent.
```cpp
case NODE_ON_DRAG_START: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"NODE_ON_DRAG_START EventReceiver");
OH_UdmfRecord *record = OH_UdmfRecord_Create();
int returnValue;
OH_UdsFileUri *imageValue = OH_UdsFileUri_Create();
returnValue = OH_UdsFileUri_SetFileUri(imageValue, "/pages/common/1111.png");
returnValue = OH_UdmfRecord_AddFileUri(record, imageValue);
OH_UdmfData *data = OH_UdmfData_Create();
returnValue = OH_UdmfData_AddRecord(data, record);
returnVaule = OH_ArkUI_DragEvent_SetData(dragEvent, data);
break;
}
```
- Handle the NODE_ON_DROP event.
In the NODE_ON_DROP event, perform operations related to the drop phase, typically involving retrieving the data passed during the drag process. For example, obtain udmfData, check whether the required data type exists, extract the corresponding data from UdmfRecord, and destroy the pointer.
```cpp
case NODE_ON_DROP: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"NODE_ON_DRAG_START EventReceiver");
// Obtain the UDMF data.
int returnValue;
// Create an OH_UdmfData object.
OH_UdmfData *data = OH_UdmfData_Create();
returnValue = OH_ArkUI_DragEvent_GetUdmfData(dragEvent, data);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"OH_ArkUI_DragEvent_GetUdmfData returnValue = %{public}d", returnValue);
// Check whether OH_UdmfData has the required data type.
bool resultUdmf = OH_UdmfData_HasType(data, UDMF_META_GENERAL_FILE);
if (resultUdmf) {
// Obtain records from OH_UdmfData.
unsigned int recordsCount = 0;
OH_UdmfRecord **records = OH_UdmfData_GetRecords(data, &recordsCount);
// Extract elements from records.
int returnStatus;
for (int i = 0; i < recordsCount; i++) {
// Obtain the file type data from OH_UdmfRecord.
OH_UdsFileUri *imageValue = OH_UdsFileUri_Create();
returnStatus = OH_UdmfRecord_GetFileUri(records[i], imageValue);
const char* fileUri = OH_UdsFileUri_GetFileUri(imageValue);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"dragTest OH_UdmfRecord_GetPlainText "
"returnStatus= %{public}d "
"fileUri= %{public}s",
returnStatus, fileUri);
// Destroy the pointer after use.
OH_UdsFileUri_Destroy(imageValue);
}
} else {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"OH_UdmfData_HasType not contain UDMF_META_PLAIN_TEXT");
}
break;
}
```
Initiating a Drag Operation
In addition to the basic drag-and-drop functionality, ArkUI allows you to initiate a drag operation using C APIs. The following example demonstrates how to use C APIs to start a drag operation with text data and highlights key points to keep in mind during development.
- Register node events.
Create a Button node, set its attributes, and register the NODE_ON_TOUCH_INTERCEPT event.
```cpp
// Use buttonTouch as targetId to distinguish events from different targets.
enum {
buttonTouch
}
ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
auto button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
ArkUI_AttributeItem NODE_Button_SRC_Item = {.string = "button"};
ArkUI_NumberValue buttonWidthValue[] = {200};
ArkUI_AttributeItem buttonWidthItem = {buttonWidthValue, 1};
ArkUI_NumberValue buttonHeightValue[] = {100};
ArkUI_AttributeItem buttonHeightItem = {buttonHeightValue, 1};
ArkUI_NumberValue marginValue[] = {20};
ArkUI_AttributeItem marginItem = {marginValue, 1};
nodeAPI->setAttribute(button, NODE_WIDTH, &buttonWidthItem);
nodeAPI->setAttribute(button, NODE_HEIGHT, &buttonHeightItem);
nodeAPI->setAttribute(button, NODE_MARGIN, &marginItem);
nodeAPI->setAttribute(button, NODE_BUTTON_LABEL, &NODE_Button_SRC_Item);
nodeAPI->registerNodeEvent(button, NODE_ON_TOUCH_INTERCEPT, buttonTouch, nullptr);
```
Receive the NODE_ON_TOUCH_INTERCEPT event.
In the NODE_ON_TOUCH_INTERCEPT event, you need to set up DragAction to initiate the drag operation. Use targetId to distinguish events triggered by different buttons.
nodeAPI->registerNodeEventReceiver([](ArkUI_NodeEvent *event) { auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); auto targetId = OH_ArkUI_NodeEvent_GetTargetId(event); ArkUI_NodeHandle node = OH_ArkUI_NodeEvent_GetNodeHandle(event); auto *dragEvent = OH_ArkUI_NodeEvent_GetDragEvent(event); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "targetId=%{public}d,eventType=%{public}d,", targetId, eventType); switch (eventType) { case NODE_ON_TOUCH_INTERCEPT: { OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "ARKUI_NODE_BUTTON touch intercept"); break; switch (targetId) { case buttonTouch: { OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "dragTest button touch!"); } } } case NODE_ON_DROP: { OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "NODE_ON_DROP EventReceiver"); } } });
Set the drag action.
In the NODE_ON_TOUCH_INTERCEPT event, set DragAction to initiate the drag operation. Create a PixelMap, set dragPreviewOption and the touch point, and set the text data for the drag operation.
case NODE_ON_TOUCH_INTERCEPT: { // Set a PixelMap object. uint8_t data[960000]; size_t dataSize = 960000; for (int i = 0; i < dataSize; i++) { data[i] = i + 1; } // Create a parameter structure instance and set parameters. OH_Pixelmap_InitializationOptions *createOpts; OH_PixelmapInitializationOptions_Create(&createOpts); OH_PixelmapInitializationOptions_SetWidth(createOpts, 200); OH_PixelmapInitializationOptions_SetHeight(createOpts, 300); OH_PixelmapInitializationOptions_SetPixelFormat(createOpts, PIXEL_FORMAT_BGRA_8888); OH_PixelmapInitializationOptions_SetAlphaType(createOpts, PIXELMAP_ALPHA_TYPE_UNKNOWN); // Create a Pixelmap instance. OH_PixelmapNative *pixelmap = nullptr; OH_PixelmapNative_CreatePixelmap(data, dataSize, createOpts, &pixelmap); OH_PixelmapNative_Rotate(pixelmap, 90.0); OH_PixelmapNative_Opacity(pixelmap, 0.2); OH_PixelmapNative_Scale(pixelmap, 0.8, 1.0); OH_PixelmapNative_Flip(pixelmap, true, true); std::vector<OH_PixelmapNative *> pixelVector; pixelVector.push_back(pixelmap); int returnValue; switch (targetId) { case buttonTouch: { // CreateDragAction auto action1 = OH_ArkUI_CreateDragActionWithNode(node); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_CreateDragActionWithNode returnValue = %{public}p", action1); returnValue = OH_ArkUI_DragAction_SetPixelMaps(action1, pixelVector.data(), pixelVector.size()); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_DragAction_SetPixelMaps returnValue = %{public}d", returnValue); // Set DragPreviewOption. auto *previewOptions1 = OH_ArkUI_CreateDragPreviewOption(); OH_ArkUI_DragPreviewOption_SetScaleMode( previewOptions1, ArkUI_DragPreviewScaleMode::ARKUI_DRAG_PREVIEW_SCALE_DISABLED); OH_ArkUI_DragPreviewOption_SetDefaultShadowEnabled(previewOptions1, true); OH_ArkUI_DragPreviewOption_SetDefaultRadiusEnabled(previewOptions1, true); returnValue = OH_ArkUI_DragAction_SetDragPreviewOption(action1, previewOptions1); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_DragAction_SetDragPreviewOption returnValue = %{public}d", returnValue); // Set pointerId. returnValue = OH_ArkUI_DragAction_SetPointerId(action1, 0); //-1 0 10 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_DragAction_SetPointerId returnValue = %{public}d", returnValue); // Set the touch point. returnValue = OH_ArkUI_DragAction_SetTouchPointX(action1, 200); //-1 0 200 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_DragAction_SetTouchPointX returnValue = %{public}d", returnValue); returnValue = OH_ArkUI_DragAction_SetTouchPointY(action1, 200); //-1 0 200 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_DragAction_SetTouchPointY returnValue = %{public}d", returnValue); // Set unifiedData. // Create an OH_UdmfRecord object. OH_UdmfRecord *record = OH_UdmfRecord_Create(); // Add plain text data to OH_UdmfRecord. OH_UdsPlainText *plainText = OH_UdsPlainText_Create(); int returnStatus; OH_UdsPlainText_SetAbstract(plainText, "this is plainText Abstract example"); OH_UdsPlainText_SetContent(plainText, "this is plainText Content example"); returnStatus = OH_UdmfRecord_AddPlainText(record, plainText); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "dragTest OH_UdmfRecord_AddPlainText returnStatus = %{public}d", returnStatus); // Create an OH_UdmfData object. OH_UdmfData *data = OH_UdmfData_Create(); // Add OH_UdmfRecord to OH_UdmfData. returnStatus = OH_UdmfData_AddRecord(data, record); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "dragTest OH_UdmfData_AddRecord returnStatus = %{public}d", returnStatus); returnValue = OH_ArkUI_DragAction_SetData(action1, data); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_DragAction_SetData returnValue = %{public}d", returnValue); // startDrag returnValue = OH_ArkUI_StartDrag(action1); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "OH_ArkUI_StartDrag returnValue = %{public}d", returnValue); OH_ArkUI_DragAction_Dispose(action1); } } }
Handle the NODE_ON_DROP event.
In the NODE_ON_DROP event, perform actions related to the drop phase. Typically, this involves obtaining the data passed during the drag operation. The drag data from DragAction is also obtained through DragEvent
```cpp
case NODE_ON_DROP: {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest", "NODE_ON_DROP EventReceiver");
// Obtain the UDMF data.
int returnValue;
// Create an OH_UdmfData object.
OH_UdmfData *data = OH_UdmfData_Create();
returnValue = OH_ArkUI_DragEvent_GetUdmfData(dragEvent, data);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"OH_ArkUI_DragEvent_GetUdmfData returnValue = %{public}d", returnValue);
// Check whether OH_UdmfData has the required data type.
bool resultUdmf = OH_UdmfData_HasType(data, UDMF_META_PLAIN_TEXT);
if (resultUdmf) {
// Obtain records from OH_UdmfData.
unsigned int recordsCount = 0;
OH_UdmfRecord **records = OH_UdmfData_GetRecords(data, &recordsCount);
// Extract elements from records.
int returnStatus;
for (int i = 0; i < recordsCount; i++) {
// Obtain plain text data from OH_UdmfRecord.
OH_UdsPlainText *plainTextValue = OH_UdsPlainText_Create();
returnStatus = OH_UdmfRecord_GetPlainText(records[i], plainTextValue);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"dragTest OH_UdmfRecord_GetPlainText "
"returnStatus= %{public}d",
returnStatus);
auto getAbstract = OH_UdsPlainText_GetAbstract(plainTextValue);
auto getContent = OH_UdsPlainText_GetContent(plainTextValue);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"OH_UdsPlainText_GetAbstract = "
"%{public}s, OH_UdsPlainText_GetContent = "
"%{public}s",
getAbstract, getContent);
// Destroy the pointer after use.
OH_UdsPlainText_Destroy(plainTextValue);
}
} else {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "dragTest",
"OH_UdmfData_HasType not contain UDMF_META_PLAIN_TEXT");
}
break;
}
```
你可能感兴趣的鸿蒙文章
harmony 鸿蒙Atomic Service Full Screen Launch Component (FullScreenLaunchComponent)
harmony 鸿蒙Arc Button (ArcButton)
harmony 鸿蒙Frame Animation (ohos.animator)
harmony 鸿蒙Implementing Property Animation
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦