diff --git a/README.md b/README.md index 22a45f2098ccfd355243ebc0fb739387f65208c9..bc105f1d14184138e00440c30513b22fbb5240cd 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,39 @@ # 多API版本兼容示例 ### 介绍 -通过@ohos.deviceInfo(设备信息)模块deviceInfo.sdkApiVersion和deviceInfo.distributionOSApiVersion获取系统SDK版本,以Text、Scroll和HdsActionBar组件在API 18和API 20的兼容为例,介绍多版本适配的实现方法。 +通过@ohos.deviceInfo(设备信息)模块deviceInfo.sdkApiVersion和deviceInfo.distributionOSApiVersion获取系统SDK版本,以Text、Scroll和HdsActionBar组件在API 18和API 20的兼容为例,介绍多版本适配的实现方法。在Native侧,通过deviceinfo的OH_GetSdkApiVersion获取系统SDK版本,以Button组件为例介绍多版本适配的实现方法。 ### 工程目录 ``` +|──entry/src/main/cpp +| |──classdef +| | |──include +| | | |──ArkUIBaseNode.h // 组件树操作的基类 +| | | |──ArkUINode.h // 通用组件的封装 +| | | |──ArkUIButtonNode.h // 实现按钮组件的封装类 +| | | └──NativeModuleInstance.h // ArkUI在Native侧模块的封装接口 +| | └──src +| | | |──ArkUIBaseNode.cpp // 组件树操作的基类 +| | | |──ArkUINode.cpp // 通用组件的封装 +| | | |──ArkUIButtonNode.cpp // 实现按钮组件的封装类 +| | | └──NativeModuleInstance.cpp // ArkUI在Native侧模块的封装接口 +| |──function +| | |──include +| | | |──IntegratingWithArkts.h // 接入ArkTS界面 +| | | └──NativeEntry.h // 管理Native组件生命周期 +| | └──src +| | | └──IntegratingWithArkts.cpp // 接入ArkTS界面 +| └──types +| | └──libentry +| | | |──Index.d.ts // Native侧接口导出声明文件 +| | | └──oh-package.json5 +| |──CMakeLists.txt // cmake配置文件 +| └──napi_init.cpp // 接口映射、模块注册 ├──entry/src/main/ets // 代码区 │ ├──components // 自定义组件 -│ │ ├──ActionBarAdapter.ets // HdsActionBar组件版本兼容示例 +│ │ ├──ActionBarAdapter.ets // HdsActionBar组件版本兼容示例 +│ │ ├──NativeButtonAdapter.ets // Button组件版本兼容示例 │ │ ├──ScrollComponentAdapter.ets // Scroll组件版本兼容示例 │ │ └──TextComponentAdapter.ets // Text组件版本兼容示例 │ ├──entryability @@ -27,6 +52,7 @@ * 以Text组件的marqueeOptions属性使用为例来展示API18的兼容,实现了跑马灯效果 * 以Scroll组件的maxZoomScale、minZoomScale和enableBouncesZoom为例子来展示API20的兼容,实现了图片缩放效果。 * 以HdsActionBar组件的使用例子来展示API20的兼容,实现可以展开和收起的ActionBar效果。 +* 以Native侧的Button组件为例,展示API20的兼容。 ### 相关权限 不涉及 diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 index 4d611879c7913fb0610c686e2399258ab3a6dad1..d348bc7b5829abb92ac32f365731164831747fb8 100644 --- a/entry/build-profile.json5 +++ b/entry/build-profile.json5 @@ -1,6 +1,15 @@ { "apiType": "stageMode", "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": [ + "arm64-v8a", + "x86_64" + ], + } }, "buildOptionSet": [ { diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 index 248c3b7541a589682a250f86a6d3ecf7414d2d6a..49272b92c5bf80d3b57b46e03664b86eae213cb5 100644 --- a/entry/oh-package.json5 +++ b/entry/oh-package.json5 @@ -5,6 +5,8 @@ "main": "", "author": "", "license": "", - "dependencies": {} + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } } diff --git a/entry/src/main/cpp/CMakeLists.txt b/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..eccba73b47b604f39f0a2a63da2655f0459cb91d --- /dev/null +++ b/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,25 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(NDKCreateUI) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +set(CMAKE_CXX_STANDARD 17) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/classdef/include + ${NATIVERENDER_ROOT_PATH}/function/include) + +file(GLOB BASECLADD_SOURCES "./classdef/src/*.cpp") + +file(GLOB FUNCTION_SOURCES "./function/src/*.cpp") + +add_library(entry SHARED + napi_init.cpp + ${BASECLADD_SOURCES} + ${FUNCTION_SOURCES}) + +target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so libhilog_ndk.z.so libnative_drawing.so libuv.so libdeviceinfo_ndk.z.so) \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/include/ArkUIBaseNode.h b/entry/src/main/cpp/classdef/include/ArkUIBaseNode.h new file mode 100644 index 0000000000000000000000000000000000000000..6e7549ea8a031bc30187a74ae03b2a92a6c920b3 --- /dev/null +++ b/entry/src/main/cpp/classdef/include/ArkUIBaseNode.h @@ -0,0 +1,62 @@ +/* + * 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 NDKCREATEUI_ARKUIBASENODE_H +#define NDKCREATEUI_ARKUIBASENODE_H + +#include +#include +#include +#include "NativeModuleInstance.h" + +namespace NativeModule { +class ArkUIBaseNode { +public: + explicit ArkUIBaseNode(ArkUI_NodeHandle handle) + : handle_(handle), nativeModule_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()) {} + + virtual ~ArkUIBaseNode() + { + // Encapsulate destructor to implement the function of removing child nodes. + if (!children_.empty()) { + for (const auto &child : children_) { + nativeModule_->removeChild(handle_, child->GetHandle()); + } + children_.clear(); + } + // Encapsulate destructors to uniformly recycle node resources. + nativeModule_->disposeNode(handle_); + } + + void AddChild(const std::shared_ptr &child); + + std::list> GetChildren(); + + ArkUI_NodeHandle GetHandle() const; + +protected: + virtual void OnAddChild(const std::shared_ptr &child) {} + virtual void OnRemoveChild(const std::shared_ptr &child) {} + virtual void OnInsertChild(const std::shared_ptr &child, int32_t index) {} + + ArkUI_NodeHandle handle_; + ArkUI_NativeNodeAPI_1 *nativeModule_ = nullptr; + +private: + std::list> children_; +}; +} // namespace NativeModule + +#endif // NDKCREATEUI_ARKUIBASENODE_H \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/include/ArkUIButtonNode.h b/entry/src/main/cpp/classdef/include/ArkUIButtonNode.h new file mode 100644 index 0000000000000000000000000000000000000000..a1804d7c6eea8e5ecdd16b6bb9e2f89d6c599c2f --- /dev/null +++ b/entry/src/main/cpp/classdef/include/ArkUIButtonNode.h @@ -0,0 +1,40 @@ +/* + * 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 NDKCREATEUI_ARKUI_BUTTON_H +#define NDKCREATEUI_ARKUI_BUTTON_H + +#include "ArkUINode.h" + +namespace NativeModule { +class ArkUIButtonNode : public ArkUINode { +public: + ArkUIButtonNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_BUTTON)) {} + + // Text attribute NDK interface encapsulation. + void SetFontSize(float fontSize); + + void SetFontColor(uint32_t color); + + void SetTextContent(const std::string &content); + + void SetTextAlign(ArkUI_TextAlignment align); + + void SetButtonType(int32_t buttonType); +}; +} // namespace NativeModule + +#endif // NDKCREATEUI_ARKUITEXTNODE_H \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/include/ArkUINode.h b/entry/src/main/cpp/classdef/include/ArkUINode.h new file mode 100644 index 0000000000000000000000000000000000000000..c28a5a0b4fa578abd367f7724ae461dc0fe488f6 --- /dev/null +++ b/entry/src/main/cpp/classdef/include/ArkUINode.h @@ -0,0 +1,94 @@ +/* + * 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 NDKCREATEUI_ARKUINODE_H +#define NDKCREATEUI_ARKUINODE_H + +#include "ArkUIBaseNode.h" +#include "NativeModuleInstance.h" + +namespace NativeModule { +class ArkUINode : public ArkUIBaseNode { +public: + explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) + { + nativeModule_ = NativeModuleInstance::GetInstance()->GetNativeNodeAPI(); + // When an event is triggered, the corresponding event object needs to be obtained through a function. + // Here, the encapsulated class pointer is kept on the component by setting node custom data, + // which facilitates subsequent event distribution. + nativeModule_->setUserData(handle_, this); + // Register a node to listen for event receivers. + nativeModule_->addNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver); + } + + ~ArkUINode() override + { + if (onClick_) { + nativeModule_->unregisterNodeEvent(handle_, NODE_ON_CLICK); + } + if (onTouch_) { + nativeModule_->unregisterNodeEvent(handle_, NODE_TOUCH_EVENT); + } + if (onDisappear_) { + nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR); + } + if (onAppear_) { + nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_APPEAR); + } + nativeModule_->removeNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver); + } + + void SetWidth(float width); + + void SetPercentWidth(float percent); + + void SetHeight(float height); + + void SetPercentHeight(float percent); + + void SetBackgroundColor(uint32_t color); + + // Handle general events. + void RegisterOnClick(const std::function &onClick); + + // Node disappearance event. + void RegisterOnDisappear(const std::function &onDisappear); + + // Node occurrence event. + void RegisterOnAppear(const std::function &onAppear); + +protected: + // Pointer to the event listener function. + static void NodeEventReceiver(ArkUI_NodeEvent *event); + + void ProcessNodeEvent(ArkUI_NodeEvent *event); + + virtual void OnNodeEvent(ArkUI_NodeEvent *event) {} + + void OnAddChild(const std::shared_ptr &child) override; + + void OnRemoveChild(const std::shared_ptr &child) override; + + void OnInsertChild(const std::shared_ptr &child, int32_t index) override; + +private: + std::function onClick_; + std::function onDisappear_; + std::function onAppear_; + std::function onTouch_; +}; +} // namespace NativeModule + +#endif // NDKCREATEUI_ARKUINODE_H \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/include/NativeModuleInstance.h b/entry/src/main/cpp/classdef/include/NativeModuleInstance.h new file mode 100644 index 0000000000000000000000000000000000000000..da2059e6bb4372144e6056ce4d8800bc6a6bfe5a --- /dev/null +++ b/entry/src/main/cpp/classdef/include/NativeModuleInstance.h @@ -0,0 +1,48 @@ +/* + * 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 NDKCREATEUI_NATIVEMODULE_H +#define NDKCREATEUI_NATIVEMODULE_H + +#include +#include +#include + +namespace NativeModule { +class NativeModuleInstance { +public: + static NativeModuleInstance *GetInstance() + { + static NativeModuleInstance instance; + return &instance; + } + + NativeModuleInstance() + { + // Retrieve the function pointer structure object of the NDK interface for subsequent operations. + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, arkUINativeNodeApi_); + if (!arkUINativeNodeApi_) { + return; + } + } + // Expose to other modules for use. + ArkUI_NativeNodeAPI_1 *GetNativeNodeAPI(); + +private: + ArkUI_NativeNodeAPI_1 *arkUINativeNodeApi_ = nullptr; +}; +} // namespace NativeModule + +#endif // NDKCREATEUI_NATIVEMODULE_H \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/src/ArkUIBaseNode.cpp b/entry/src/main/cpp/classdef/src/ArkUIBaseNode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbe80dbaa620bcceb4889464087db24ec3420068 --- /dev/null +++ b/entry/src/main/cpp/classdef/src/ArkUIBaseNode.cpp @@ -0,0 +1,28 @@ +/* + * 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 "ArkUIBaseNode.h" + +namespace NativeModule { +void ArkUIBaseNode::AddChild(const std::shared_ptr &child) +{ + children_.emplace_back(child); + OnAddChild(child); +} + +std::list> ArkUIBaseNode::GetChildren() { return children_; } + +ArkUI_NodeHandle ArkUIBaseNode::GetHandle() const { return handle_; } +} // namespace NativeModule \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/src/ArkUIButtonNode.cpp b/entry/src/main/cpp/classdef/src/ArkUIButtonNode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2190ae1434b45ac3dfeac768a62baf9cd8c8f0fb --- /dev/null +++ b/entry/src/main/cpp/classdef/src/ArkUIButtonNode.cpp @@ -0,0 +1,59 @@ +/* + * 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 +#include "ArkUIButtonNode.h" + +namespace NativeModule { +// Text attribute NDK interface encapsulation. +void ArkUIButtonNode::SetFontSize(float fontSize) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.f32 = fontSize}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_FONT_SIZE, &item); +} + +void ArkUIButtonNode::SetFontColor(uint32_t color) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.u32 = color}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_FONT_COLOR, &item); +} + +void ArkUIButtonNode::SetTextContent(const std::string &content) +{ + assert(handle_); + ArkUI_AttributeItem item = {nullptr, 0, content.c_str()}; + nativeModule_->setAttribute(handle_, NODE_BUTTON_LABEL, &item); +} + +void ArkUIButtonNode::SetTextAlign(ArkUI_TextAlignment align) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.i32 = align}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_TEXT_ALIGN, &item); +} + +void ArkUIButtonNode::SetButtonType(int32_t buttonType) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.i32 = buttonType}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_BUTTON_TYPE , &item); +} +} // namespace NativeModule \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/src/ArkUINode.cpp b/entry/src/main/cpp/classdef/src/ArkUINode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..832b3d2979012a70a6e8cb757baf8aca333f308a --- /dev/null +++ b/entry/src/main/cpp/classdef/src/ArkUINode.cpp @@ -0,0 +1,154 @@ +/* + * 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 "ArkUINode.h" + +namespace NativeModule { +void ArkUINode::SetWidth(float width) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.f32 = width}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_WIDTH, &item); +} + +void ArkUINode::SetPercentWidth(float percent) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.f32 = percent}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item); +} + +void ArkUINode::SetHeight(float height) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.f32 = height}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item); +} + +void ArkUINode::SetPercentHeight(float percent) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.f32 = percent}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item); +} + +void ArkUINode::SetBackgroundColor(uint32_t color) +{ + assert(handle_); + ArkUI_NumberValue value[] = {{.u32 = color}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item); +} + +// Handle general events. +void ArkUINode::RegisterOnClick(const std::function &onClick) +{ + assert(handle_); + onClick_ = onClick; + // 注册点击事件。 + nativeModule_->registerNodeEvent(handle_, NODE_ON_CLICK, 0, nullptr); +} + +// Node disappearance event. +void ArkUINode::RegisterOnDisappear(const std::function &onDisappear) +{ + if (!handle_) { + throw std::runtime_error("handle_ is null!"); + } + onDisappear_ = onDisappear; + // Register for uninstallation events. + nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR, 0, nullptr); +} + +// Node occurrence event. +void ArkUINode::RegisterOnAppear(const std::function &onAppear) +{ + if (!handle_) { + throw std::runtime_error("handle_ is null!"); + } + onAppear_ = onAppear; + // Register mount event. + nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr); +} + +// Pointer to the event listener function. +void ArkUINode::NodeEventReceiver(ArkUI_NodeEvent *event) +{ + // Retrieve the UI component object where the event occurred. + auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event); + // Retrieve custom data held in the UI component object and return the wrapper class pointer. + auto *node = + reinterpret_cast(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle)); + // Process events based on encapsulated class instance objects. + node->ProcessNodeEvent(event); +} + +void ArkUINode::ProcessNodeEvent(ArkUI_NodeEvent *event) +{ + auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); + switch (eventType) { + case NODE_ON_CLICK: { + if (onClick_) { + onClick_(); + } + break; + } + case NODE_TOUCH_EVENT: { + if (onTouch_) { + auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event); + float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent); + float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent); + auto type = OH_ArkUI_UIInputEvent_GetAction(uiInputEvent); + onTouch_(type, x, y); + } + } + case NODE_EVENT_ON_DISAPPEAR: { + if (onDisappear_) { + onDisappear_(); + } + break; + } + case NODE_EVENT_ON_APPEAR: { + if (onAppear_) { + onAppear_(); + } + break; + } + default: { + // Assign component specific events to subclasses for processing. + OnNodeEvent(event); + } + } +} + +void ArkUINode::OnAddChild(const std::shared_ptr &child) +{ + nativeModule_->addChild(handle_, child->GetHandle()); +} + +void ArkUINode::OnRemoveChild(const std::shared_ptr &child) +{ + nativeModule_->removeChild(handle_, child->GetHandle()); +} + +void ArkUINode::OnInsertChild(const std::shared_ptr &child, int32_t index) +{ + nativeModule_->insertChildAt(handle_, child->GetHandle(), index); +} +} // namespace NativeModule \ No newline at end of file diff --git a/entry/src/main/cpp/classdef/src/NativeModuleInstance.cpp b/entry/src/main/cpp/classdef/src/NativeModuleInstance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c27bc4816e6c786d2c4d856743cf1c01f9bcbe07 --- /dev/null +++ b/entry/src/main/cpp/classdef/src/NativeModuleInstance.cpp @@ -0,0 +1,20 @@ +/* + * 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 "NativeModuleInstance.h" + +namespace NativeModule { +ArkUI_NativeNodeAPI_1 *NativeModuleInstance::GetNativeNodeAPI() { return arkUINativeNodeApi_; } +} // namespace NativeModule \ No newline at end of file diff --git a/entry/src/main/cpp/function/include/IntegratingWithArkts.h b/entry/src/main/cpp/function/include/IntegratingWithArkts.h new file mode 100644 index 0000000000000000000000000000000000000000..edcecdfc05d114870a175dc86cb4c965b87f3a48 --- /dev/null +++ b/entry/src/main/cpp/function/include/IntegratingWithArkts.h @@ -0,0 +1,35 @@ +/* + * 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 NDKCREATEUI_INTEGRATINGWITHARKTS_H +#define NDKCREATEUI_INTEGRATINGWITHARKTS_H + +#include +#include +#include "ArkUIBaseNode.h" + +namespace NativeModule { +constexpr int32_t List_NUM = 30; +constexpr int32_t TEXT_FONTSIZE = 16; +constexpr int32_t TEXT_HEIGHT = 100; + +napi_value CreateButtonNativeRoot(napi_env env, napi_callback_info info); + +napi_value DestroyButtonNativeRoot(napi_env env, napi_callback_info info); + +std::shared_ptr CreateButtonExample(); +} // namespace NativeModule + +#endif // NDKCREATEUI_INTEGRATINGWITHARKTS_H diff --git a/entry/src/main/cpp/function/include/NativeEntry.h b/entry/src/main/cpp/function/include/NativeEntry.h new file mode 100644 index 0000000000000000000000000000000000000000..c744e84d0aa5b423206a045cc79727e1b2320030 --- /dev/null +++ b/entry/src/main/cpp/function/include/NativeEntry.h @@ -0,0 +1,49 @@ +/* + * 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 NDKCREATEUI_NATIVEENTRY_H +#define NDKCREATEUI_NATIVEENTRY_H + +#include +#include "ArkUIBaseNode.h" + +namespace NativeModule { +// Manage the lifecycle and memory of native components. +class NativeEntry { +public: + // Set handle content. + void SetContentHandle(ArkUI_NodeContentHandle handle) { handle_ = handle; } + + void SetRootNode(const std::shared_ptr &baseNode) + { + root_ = baseNode; + // Add Native components to NodeContent for mounting display. + OH_ArkUI_NodeContent_AddNode(handle_, root_->GetHandle()); + } + + void DisposeRootNode() + { + // Uninstall components from NodeContent and destroy native components. + OH_ArkUI_NodeContent_RemoveNode(handle_, root_->GetHandle()); + root_.reset(); + } + +private: + std::shared_ptr root_; + ArkUI_NodeContentHandle handle_; +}; +} // namespace NativeModule + +#endif // NDKCREATEUI_NATIVEENTRY_H \ No newline at end of file diff --git a/entry/src/main/cpp/function/src/IntegratingWithArkts.cpp b/entry/src/main/cpp/function/src/IntegratingWithArkts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4d5cec7e3955c536137393bb9af256a77bd15f7 --- /dev/null +++ b/entry/src/main/cpp/function/src/IntegratingWithArkts.cpp @@ -0,0 +1,69 @@ +/* + * 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 +#include +#include "ArkUIButtonNode.h" +#include "NativeEntry.h" +#include "IntegratingWithArkts.h" +#include + +namespace NativeModule { +NativeEntry nativeEntry; + +napi_value CreateButtonNativeRoot(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + // Get parameters passed in from JS. + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + // Get NodeContent. + ArkUI_NodeContentHandle contentHandle; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + nativeEntry.SetContentHandle(contentHandle); + + // Create a text list. + auto list = CreateButtonExample(); + // Keep the Native side objects in the management class and maintain their lifecycle. + nativeEntry.SetRootNode(list); + + return nullptr; +} + +std::shared_ptr CreateButtonExample() +{ + auto textNode = std::make_shared(); + textNode->SetTextContent(std::string("Hello World")); + textNode->SetFontSize(TEXT_FONTSIZE); + textNode->SetPercentWidth(1); + textNode->SetHeight(50); + textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); + if (OH_GetSdkApiVersion() >= 19) { + textNode->SetButtonType(ARKUI_BUTTON_ROUNDED_RECTANGLE); + } else { + textNode->SetButtonType(ARKUI_BUTTON_TYPE_CAPSULE); + } + + return textNode; +} + +napi_value DestroyButtonNativeRoot(napi_env env, napi_callback_info info) +{ + nativeEntry.DisposeRootNode(); + return nullptr; +} +} // namespace NativeModule \ No newline at end of file diff --git a/entry/src/main/cpp/napi_init.cpp b/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3dbe3f3497de8d125588977a17708c3d5218cf30 --- /dev/null +++ b/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,50 @@ +/* + * 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 +#include "IntegratingWithArkts.h" + +EXTERN_C_START +// Registration of components related to the encapsulation list. +void RegisterListComponents(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + {"CreateButtonNativeRoot", nullptr, NativeModule::CreateButtonNativeRoot, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"DestroyButtonNativeRoot", nullptr, NativeModule::DestroyButtonNativeRoot, nullptr, nullptr, nullptr, + napi_default, nullptr}, + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); +} + +static napi_value Init(napi_env env, napi_value exports) +{ + // Bind the creation and destruction components on the native side. + RegisterListComponents(env, exports); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } \ No newline at end of file diff --git a/entry/src/main/cpp/types/libentry/Index.d.ts b/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..213acecd0d498a8be395609608dff52345f77203 --- /dev/null +++ b/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,20 @@ +/* + * 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 { NodeContent } from "@kit.ArkUI"; + +export const CreateButtonNativeRoot: (content: NodeContent) => void; + +export const DestroyButtonNativeRoot: () => void; \ No newline at end of file diff --git a/entry/src/main/cpp/types/libentry/oh-package.json5 b/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ea410725a8826704d061021d98cf02aa76cd8016 --- /dev/null +++ b/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,6 @@ +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/entry/src/main/ets/components/NativeButtonAdapter.ets b/entry/src/main/ets/components/NativeButtonAdapter.ets new file mode 100644 index 0000000000000000000000000000000000000000..fd99dd4386e36c9dc8be3642375c128318600904 --- /dev/null +++ b/entry/src/main/ets/components/NativeButtonAdapter.ets @@ -0,0 +1,42 @@ +/* + * 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 { NodeContent } from '@kit.ArkUI'; +import nativeNode from 'libentry.so'; + + +@Component +export struct NativeButtonAdapter { + private rootSlot = new NodeContent(); + + aboutToAppear(): void { + nativeNode.CreateButtonNativeRoot(this.rootSlot); + } + + aboutToDisappear(): void { + nativeNode.DestroyButtonNativeRoot(); + } + + build() { + Column() { + Row() { + // Bind NodeContent and ContentSlot placeholder components. + ContentSlot(this.rootSlot) + } + } + .width('100%') + .height('30%') + } +} diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 8bb60475fe885e1f2e248c894384f66fa460d476..90d1e6d188728732bf8b0c2d1f13ee700ea168fc 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -16,6 +16,7 @@ import { ScrollComponentAdapter } from '../components/ScrollComponentAdapter'; import { TextComponentAdapter } from '../components/TextComponentAdapter'; import { ActionBarAdapter } from '../components/ActionBarAdapter'; +import { NativeButtonAdapter } from '../components/NativeButtonAdapter'; @Entry @Component @@ -25,6 +26,7 @@ struct Index { ScrollComponentAdapter() TextComponentAdapter() ActionBarAdapter() + NativeButtonAdapter() } .height('100%') .width('100%')