From f0ce0d9a4521274bbd66a84a5c6ea718448dd93a Mon Sep 17 00:00:00 2001 From: wangjunman1 Date: Mon, 29 Sep 2025 15:37:59 +0800 Subject: [PATCH] add Signed-off-by: wangjunman1 --- ArkUIKit/NativeTypeSample/README.md | 3 + .../entry/src/main/cpp/CMakeLists.txt | 10 +- .../entry/src/main/cpp/XComponentMaker.cpp | 111 ++++++++++++++++++ .../entry/src/main/cpp/XComponentMaker.h | 29 +++++ .../entry/src/main/cpp/manager.cpp | 63 ++++++++++ .../entry/src/main/cpp/manager.h | 3 + .../entry/src/main/cpp/napi_init.cpp | 2 + .../src/main/cpp/types/libentry/Index.d.ts | 3 +- .../entry/src/main/ets/pages/Index.ets | 1 + .../src/main/ets/pages/page_xcomponent.ets | 71 +++++++++++ .../resources/base/profile/main_pages.json | 1 + ArkUIKit/NativeTypeSample/ohosTest.md | 3 +- 12 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.cpp create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.h create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_xcomponent.ets diff --git a/ArkUIKit/NativeTypeSample/README.md b/ArkUIKit/NativeTypeSample/README.md index 6a849823f..10fcdb436 100644 --- a/ArkUIKit/NativeTypeSample/README.md +++ b/ArkUIKit/NativeTypeSample/README.md @@ -27,6 +27,7 @@ entry/src/main/ets/ ├── page_text.ets (文本界面) ├── page_swiper.ets (滑动容器页面) ├── page_accessibility.ets (无障碍界面) + ├──page_xcomponent.ets (XComponent界面) └── page_embedded_component.ets (嵌入式组件界面) entry/src/main/ ├── cpp @@ -55,6 +56,8 @@ entry/src/main/ │ ├── TextMaker.h | ├── AccessibilityMaker.cpp │ ├── AccessibilityMaker.h +| ├── XComponentMaker.cpp +│ ├── XComponentMaker.h | ├── EmbeddedComponentMaker.cpp │ └── EmbeddedComponentMaker.h └── resources diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/CMakeLists.txt b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/CMakeLists.txt index 41bdb9046..891ad94b2 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/CMakeLists.txt +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/CMakeLists.txt @@ -26,6 +26,10 @@ find_library( libace-lib libnapi-lib ace_napi.z + EGL-lib + EGL + GLES-lib + GLESv3 ) target_link_libraries(entry PUBLIC libace_ndk.z.so @@ -33,4 +37,8 @@ target_link_libraries(entry PUBLIC libhilog_ndk.z.so libnative_drawing.so libability_base_want.so -) \ No newline at end of file +) + +target_link_libraries(entry PUBLIC ${libace-lib} libace_napi.z.so libnative_drawing.so libhilog_ndk.z.so) +target_link_libraries(entry PUBLIC ${EGL-lib} ${GLES-lib} libace_napi.z.so libhilog_ndk.z.so libace_ndk.z.so libnative_window.so) +target_link_libraries(entry PUBLIC ${libace-lib} libace_napi.z.so libnative_drawing.so libhilog_ndk.z.so libability_base_want.so) \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.cpp new file mode 100644 index 000000000..07cffe59a --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "XComponentMaker.h" +#include "manager.h" +#include +#include +#include +#include +#include +#include +#include +#include "napi/native_api.h" +#include +#include +#include +#include + +#define ON_ERROR_CODE_DEMO_103501 103501 +#define ON_ERROR_CODE_DEMO_106104 106104 +#define COLUMN_MARGIN 10 +#define VALUEF f32 +#define VALUEU u32 +#define VALUEI i32 +#define XC_TWO 2 +#define XC_TEN 10 +#define XC_FORTY 40 +static void xOnEventReceive(ArkUI_NodeEvent *event) +{ + if (event == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "manager", "错误码: %d", ARKUI_ERROR_CODE_NODE_EVENT_PARAM_INVALID); + return; + } + int32_t eventId = OH_ArkUI_NodeEvent_GetTargetId(event); + ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + auto nodeHandler = OH_ArkUI_NodeEvent_GetNodeHandle(event); + switch (eventId) { + // XComponent状态异常 + case ON_ERROR_CODE_DEMO_103501: { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "manager", "错误码: %d", + ARKUI_ERROR_CODE_XCOMPONENT_STATE_INVALID); + return; + } + // 懒加载适配器未绑定到组件上 + case ON_ERROR_CODE_DEMO_106104: { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "manager", "错误码: %d", ARKUI_ERROR_CODE_ADAPTER_NOT_BOUND); + return; + } + default: + break; + } +} +ArkUI_NodeHandle XComponentMaker::CreateNodeHandle(const std::string &tag) +{ + ArkUI_NodeHandle xc; + ArkUI_NodeHandle XCHandle; + ArkUI_NodeHandle column = Manager::XnodeAPI->createNode(ARKUI_NODE_COLUMN); + XCHandle = Manager::XnodeAPI->createNode(ARKUI_NODE_XCOMPONENT); + ArkUI_NumberValue value_xc[] = {{.VALUEF = 200}}; + ArkUI_AttributeItem item_xc = {value_xc, 1}; + ArkUI_NumberValue valuexc[] = {480}; + ArkUI_NumberValue value1xc[] = {{.VALUEU = 15}, {.VALUEF = 15}}; + ArkUI_AttributeItem itemxc = {valuexc, 1, "changeSize"}; + ArkUI_AttributeItem item1xc = {value1xc, 2}; + Manager::XnodeAPI->setAttribute(column, NODE_WIDTH, &itemxc); + valuexc[0].VALUEF = COLUMN_MARGIN; + Manager::XnodeAPI->setAttribute(column, NODE_MARGIN, &itemxc); + xc = Manager::XnodeAPI->createNode(ARKUI_NODE_XCOMPONENT_TEXTURE); // 使用示例 + xc = Manager::XnodeAPI->createNode(ARKUI_NODE_XCOMPONENT); + valuexc[0].VALUEU = ARKUI_XCOMPONENT_TYPE_SURFACE; + Manager::XnodeAPI->setAttribute(xc, NODE_XCOMPONENT_TYPE, &itemxc); + Manager::XnodeAPI->setAttribute(xc, NODE_XCOMPONENT_ID, &itemxc); + Manager::XnodeAPI->setAttribute(xc, NODE_XCOMPONENT_SURFACE_SIZE, &item1xc); + Manager::XnodeAPI->setAttribute(xc, NODE_XCOMPONENT_SURFACE_RECT, &item1xc); + Manager::XnodeAPI->setAttribute(xc, NODE_XCOMPONENT_ENABLE_ANALYZER, &item1xc); + valuexc[0].VALUEI = ARKUI_XCOMPONENT_TYPE_TEXTURE; // 使用示例 + valuexc[0].VALUEI = ARKUI_XCOMPONENT_TYPE_SURFACE; + int32_t ret = Manager::XnodeAPI->setAttribute(XCHandle, NODE_XCOMPONENT_TYPE, &item_xc); + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_ set NODE_XCOMPONENT_TYPE ret=%{public}d", ret); + OH_NativeXComponent *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(XCHandle); + ArkUI_NumberValue value[] = {{.VALUEF = 1}}; + ArkUI_AttributeItem item = {value, 1}; + ArkUI_AttributeItem content = {.string = tag.c_str()}; + Manager::XnodeAPI->setAttribute(column, NODE_WIDTH_PERCENT, &item); + value[0].VALUEF = XC_FORTY; + Manager::XnodeAPI->setAttribute(column, NODE_HEIGHT, &item); + value[0].VALUEF = XC_TEN; + Manager::XnodeAPI->setAttribute(column, NODE_MARGIN, &item); + Manager::XnodeAPI->setAttribute(column, NODE_ID, &content); + ArkUI_NodeHandle text = Manager::XnodeAPI->createNode(ARKUI_NODE_TEXT); + content = {.string = "本实例仅展示接口的使用方法,不涉及具体图像的创建"}; + Manager::XnodeAPI->setAttribute(text, NODE_TEXT_CONTENT, &content); + Manager::XnodeAPI->registerNodeEvent(column, NODE_ON_CLICK, 1, nullptr); + Manager::XnodeAPI->addChild(column, text); + Manager::XnodeAPI->addChild(column, XCHandle); + Manager::XnodeAPI->addChild(column, xc); + xOnEventReceive(nullptr); //test + return column; +} \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.h b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.h new file mode 100644 index 000000000..ae5b82132 --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/XComponentMaker.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVE_TYPE_SAMPLE_XCOMPONENTMAKER_H +#define NATIVE_TYPE_SAMPLE_XCOMPONENTMAKER_H + +#include "manager.h" + +class XComponentMaker { +public: + XComponentMaker(){}; + ~XComponentMaker(){}; + + static ArkUI_NodeHandle CreateNodeHandle(const std::string &tag); +}; + +#endif diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp index fc54722cf..ffd2127d8 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp @@ -27,11 +27,14 @@ #include "WaterFlowMaker.h" #include "baseUtils.h" #include "napi/native_api.h" +#include "XComponentMaker.h" +#include #include #include #include #include #include +#include namespace ConstIde { const uint32_t NUMBER_0 = 0; @@ -418,5 +421,65 @@ napi_value Manager::CreateListNativeNode(napi_env env, napi_callback_info info) OH_ArkUI_NodeContent_AddNode(nodeContentHandle, testNode); } } + return nullptr; +} + +ArkUI_NativeNodeAPI_1 *Manager::XnodeAPI = reinterpret_cast( + OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")); + +napi_value Manager::createNativeXComponentNode(napi_env env, napi_callback_info info) +{ + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode BEGIN"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null"); + return nullptr; + } + + size_t argc = 2; + napi_value args[2] = {nullptr, nullptr}; + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed"); + } + + if (argc != 1 + 1) { + napi_throw_type_error(env, NULL, "Wrong number of arguments"); + return nullptr; + } + ArkUI_NodeContentHandle nodeContentHandle_ = nullptr; + int32_t ret = OH_ArkUI_NodeContent_SetUserData(nodeContentHandle_, + new int32_t(123)); + void *userDataNull = + OH_ArkUI_NodeContent_GetUserData(nodeContentHandle_); // 非法获取,返回空指针 + + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_); + + if (XnodeAPI == nullptr) { + return nullptr; + } + if (XnodeAPI->createNode == nullptr || XnodeAPI->addChild == nullptr) { + return nullptr; + } + auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) { + ArkUI_NodeContentHandle handle = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event); + std::string *userData = reinterpret_cast(OH_ArkUI_NodeContent_GetUserData(handle)); + if (OH_ArkUI_NodeContentEvent_GetEventType(event) == NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) { + ArkUI_NodeHandle testNode; + if (userData) { + testNode = XComponentMaker::CreateNodeHandle(*userData); + } else { + testNode = XComponentMaker::CreateNodeHandle("noUserData"); + } + OH_ArkUI_NodeContent_InsertNode(handle, testNode, 0); // 接口使用示例 + OH_ArkUI_NodeContent_RemoveNode(handle, testNode); + OH_ArkUI_NodeContent_AddNode(handle, testNode); + } else { + if (userData) { + delete userData; + userData = nullptr; + } + } + }; + OH_ArkUI_NodeContent_RegisterCallback(nodeContentHandle_, nodeContentEvent); + return nullptr; } \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h index 2ae8f0f8c..eb7b19389 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h @@ -24,6 +24,7 @@ #include #include #include +#include const unsigned int LOG_PRINT_DOMAIN = 0xFF00; napi_value createNativeRootAnimation1(napi_env env, napi_callback_info info); @@ -39,6 +40,7 @@ napi_value DestroyNativeRoot(napi_env env, napi_callback_info info); class Manager { public: static ArkUI_NativeNodeAPI_1 *nodeAPI_; + static ArkUI_NativeNodeAPI_1 *XnodeAPI; ~Manager(){}; static Manager *GetInstance() { @@ -71,6 +73,7 @@ public: static napi_value CreateScrollNativeNode(napi_env env, napi_callback_info info); static napi_value CreateRefreshNativeNode(napi_env env, napi_callback_info info); static napi_value CreateListNativeNode(napi_env env, napi_callback_info info); + static napi_value createNativeXComponentNode(napi_env env, napi_callback_info info); private: static Manager manager_; diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp index 6b677977e..a857ac272 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp @@ -61,6 +61,8 @@ static napi_value Init(napi_env env, napi_value exports) nullptr}, {"createListNativeNode", nullptr, Manager::CreateListNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"createNativeNodexc", nullptr, Manager::createNativeXComponentNode, nullptr, nullptr, nullptr, napi_default, + nullptr}, // 参考新增其他createNative方法和Maker类 }; diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts index e79315809..e8dc9f473 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -30,4 +30,5 @@ export const createWaterFlowNativeNode: (content: Object) => void; export const createGridNativeNode: (content: Object) => void; export const createScrollNativeNode: (content: Object) => void; export const createRefreshNativeNode: (content: Object) => void; -export const createListNativeNode: (content: Object) => void; \ No newline at end of file +export const createListNativeNode: (content: Object) => void; +export const createNativeNodexc: (content: Object, tag: string) => void; \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets index 409ee829c..1de41719b 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets @@ -36,6 +36,7 @@ struct MenuIndex { { title: 'Scroll', url: 'pages/page_scroll' }, { title: 'Refresh', url: 'pages/page_refresh' }, { title: 'List', url: 'pages/page_list' }, + { title: 'XComponent', url: 'pages/page_xcomponent' }, ]; build() { diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_xcomponent.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_xcomponent.ets new file mode 100644 index 000000000..c200e5a4c --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_xcomponent.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import nativeNode from 'libentry.so'; +import { NodeContent } from '@ohos.arkui.node'; + +class Params { + public insert: boolean = false + public nodeContent: NodeContent; + + constructor(insert: boolean, nodeContent: NodeContent) { + this.insert = insert; + this.nodeContent = nodeContent; + } +} + +class MyNodeContent extends NodeContent { + onAttachToWindow(): void { + // TODO + } + + onDetachFromWindow(): void { + // TODO + } + + constructor() { + super() + } +} + +@Builder +function buildNodeContent(params: Params) { + ContentSlot(params.insert ? params.nodeContent : undefined) +} + +@Entry +@Component +struct Parent { + @State insert: boolean = true + public nodeContent = new MyNodeContent() + public nodeContent2 = new MyNodeContent() + @State xcWidth: number = 200 + aboutToAppear(): void { + nativeNode.createNativeNodexc(this.nodeContent, 'nodeContent1234'); + } + + build() { + + Row() { + Column() { + buildNodeContent(new Params(this.insert, this.nodeContent)) + } + .width(this.xcWidth) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json index e96c6ab43..33fed01d3 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json +++ b/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json @@ -9,6 +9,7 @@ "pages/page_grid", "pages/page_scroll", "pages/page_refresh", + "pages/page_xcomponent", "pages/page_list" ] } diff --git a/ArkUIKit/NativeTypeSample/ohosTest.md b/ArkUIKit/NativeTypeSample/ohosTest.md index d03b4ec1a..93878b945 100644 --- a/ArkUIKit/NativeTypeSample/ohosTest.md +++ b/ArkUIKit/NativeTypeSample/ohosTest.md @@ -12,4 +12,5 @@ | TextInput 输入功能 | 应用加载完成 | 1.点击输入框尝试输入 | 1.支持输入,第一个样式内联,第二个带清除按钮 | 否 | 验证通过 | | EmbeddedComponent OnErrorCallback回调成功 | 执行 hdc shell param set persist.sys.abilityms.multi_process_model false 后重启,应用位于首页 | 1.点击首页embedded component按钮 | EmbeddedComponent onError回调被触发,打印日志{OnErrorCallback: code=100018, name=start_ability_fail, message=Start ui extension ability failed, please check the want of UIextensionAbility.} | 否 | 验证通过 | | EmbeddedComponent OnTerminatedCallback回调成功 | 执行 hdc shell param set persist.sys.abilityms.multi_process_model true 后重启,应用位于首页 | 1.点击首页embedded component按钮 | EmbeddedComponent onError回调被触发,打印日志{OnTerminatedCallback: code=0} | 否 | 验证通过 | -| 文本无障碍属性设置 | 应用位于首页 | 1.点击首页Accessibility按钮 | 观测Get日志设置属性值与Set函数一致 | 否 | 验证通过 | \ No newline at end of file +| 文本无障碍属性设置 | 应用位于首页 | 1.点击首页Accessibility按钮 | 观测Get日志设置属性值与Set函数一致 | 否 | 验证通过 | +| 验证XComponent创建成功 | 应用位于首页 | 1.点击首页XComponent按钮 | 1.包含两个XComponent显示框 | 否 | 验证通过 | \ No newline at end of file -- Gitee