diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/app.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..eb4cec2e6afa670c9b134ca104ead40d537af879 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * 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. + */ +{ + "app": { + "bundleName": "com.example.nativenodesample", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/element/string.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1aae1c8999b95f5f099c660e4fdef50bde546bc9 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NativeNodeSample" + } + ] +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/background.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/foreground.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/layered_image.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/README_zh.md b/ArkUIKit/NativeType/NativeNodeUtilsSample/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..65c49d2db3ee4d14fa80468dcb242a22596a7af3 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/README_zh.md @@ -0,0 +1,92 @@ +# ArkUI使用NODE IMAGE指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitcode.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好的理解并合理使用ArkUI提供的组件以及组件属性。通过该工程可以创建IMAGE组件并可以设置、获取、重置组件对应节点属性,对已创建的IMAGE组件进行销毁操作。该工程中代码详细描述可参考: +[显示图片 (Image)](https://gitcode.com/openharmony/docs/blob/OpenHarmony-5.0.0-Release/zh-cn/application-dev/ui/arkts-graphics-display.md)。 + + +### 效果预览 + +| 首页 | 设置图像内容顺时针旋转90度显示 | 自定义绘制内容 |自定义绘制前景背景| +|----------------------------------------|---------------------------------|-------------------------------|-------------------------------| +| ![](screenshots/NativeNode.png) |![](screenshots/device/result.png) | ![](screenshots/DrawPage.png) | ![](screenshots/NativeUI.png) + +### 使用说明 + +1. 在主界面,可以点击“选择节点类型”,创建需要的组件。 + +2. 选择组件对应的“选择节点属性”菜单列。 + +3. 通过文本输入,设置属性值。 + +4. 点击“设置属性值”,查看效果。 + +5. 点击“获取属性值”,查看已设置的属性值。 + +6. 点击“重置”,清除设置的属性。 + +7. 点击“清理”,移除创建的组件节点。 + +8. 点击“展示绘画页面”,查看绘画效果。 + +9. 点击:“返回”,返回到主页面。 + +### 工程目录 +``` +entry/src/main/cpp +|---CMakeLists.txt // 编译脚本 +|---napi_init.cpp // 实现创建、设置、获取、重置组件属性 +|---manager.cpp // 管理组件节点 +|---NativeEntry.cpp // 多线程节点管理与自定义组件实现 +|---NativeEntry.h // 核心管理类声明 +|---types + |---Index.d.ts // napi对外接口定义 +entry/src/main/ets/ +|---entryability +|---pages +| |---entry.ets // 应用主页面 +| |---drawPage +| | |---DrawPage.ets // 自定义绘制页 +| |---NativeUI +| | |---NativeUIPage.ets // 自定义绘制背景前景 +entry/src/ohosTest/ +|---ets +| |---index.test.ets // 示例代码测试代码 +``` + +### 具体实现 + +1. 在[Index.ets](entry%2Fsrc%2Fmain%2Fets%2Fpages%2FIndex.ets)文件中,通过点击按钮创建IMAGE组件节点,并通过文本输入框设置、获取、重置属性值。 +2. 在[Index.d.ts](entry%2Fsrc%2Fmain%2Fcpp%2Ftypes%2Flibentry%2FIndex.d.ts)文件中,定义napi对外接口。 +3. 在[napi_init.cpp](entry%2Fsrc%2Fmain%2Fcpp%2Fnapi_init.cpp)文件中,实现Index.d.ts中对外的接口。 +4. 在[manager.cpp](entry%2Fsrc%2Fmain%2Fcpp%2Fmanager.cpp)文件中,通过调用ArkUI的接口实现创建、设置、获取、重置组件属性。 +5. 在[NativeEntry.cpp](entry%2Fsrc%2Fmain%2Fcpp%2FNativeEntry.cpp)文件中,通过调用CreateDrawNode方法实现自定义绘制内容。 +5. 在[NativeEntry.cpp](entry%2Fsrc%2Fmain%2Fcpp%2FNativeEntry.cpp)文件中,通过调用CreateNativeRoot方法实现自定义绘制前景背景。 +5. 在[NativeEntry.cpp](entry%2Fsrc%2Fmain%2Fcpp%2FNativeEntry.cpp)文件中,通过调用CreateDrawNode方法实现隐藏自定义绘制前景背景。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例支持标准系统上运行, 支持设备:RK3568等。 + +2.本示例为Stage模型,支持API20版本SDK,版本号:6.0.0.47,镜像版本号:OpenHarmony_5.0.2.57。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/NativeNodeSample > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +```` \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/build-profile.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5438b5af2bf3d6d899ca5f90fcc048bd3f4775dc --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * 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. + */ +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + "signingConfigs": [] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/code-linter.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * 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. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/build-profile.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..bfeb27f07c5bb5a268082430be78c1c618f32371 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/build-profile.json5 @@ -0,0 +1,54 @@ +/* + * 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. + */ +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": ["arm64-v8a","x86_64"] + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/hvigorfile.ts b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/hvigorfile.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 { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/obfuscation-rules.txt b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/oh-package.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5b21e253af246edab8b6ef4f10938f4417e8bc25 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * 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. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIBaseNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIBaseNode.h new file mode 100644 index 0000000000000000000000000000000000000000..643ec3686d1e9a5cbc29c78dbb29a1c6cea5fde4 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIBaseNode.h @@ -0,0 +1,229 @@ +/* + * 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. + */ +// ArkUIBaseNode.h +// 提供组件树操作的基类。 +#ifndef MYAPPLICATION_ARKUIBASENODE_H +#define MYAPPLICATION_ARKUIBASENODE_H + +#include +#include +#include +#include + +#include "NativeModule.h" + +namespace NativeModule { + class ArkUIBaseNode { + public: + explicit ArkUIBaseNode(ArkUI_NodeHandle handle) + : handle_(handle), nativeModule_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()) {} + + virtual ~ArkUIBaseNode() + { + // 封装析构函数,实现子节点移除功能。 + if (!children_.empty()) { + for (const auto &child : children_) { + nativeModule_->removeChild(handle_, child->GetHandle()); + } + children_.clear(); + } + // 封装析构函数,统一回收节点资源。 + nativeModule_->disposeNode(handle_); + } + + void AddChild(const std::shared_ptr &child) + { + children_.emplace_back(child); + OnAddChild(child); + } + + void RemoveChild(const std::shared_ptr &child) + { + children_.remove(child); + OnRemoveChild(child); + } + + void InsertChild(const std::shared_ptr &child, int32_t index) + { + if (index >= children_.size()) { + AddChild(child); + } else { + auto iter = children_.begin(); + std::advance(iter, index); + children_.insert(iter, child); + OnInsertChild(child, index); + } + } + + void InsertChildBefore(const std::shared_ptr &child, + const std::shared_ptr &slibing) + { + auto it = std::find(children_.begin(), children_.end(), slibing); + if (it != children_.end()) { + children_.insert(it, child); + } + OnInsertChildBefore(child, slibing); + } + + void InsertChildAfter(const std::shared_ptr &child, + const std::shared_ptr &slibing) + { + auto it = std::find(children_.begin(), children_.end(), slibing); + if (it != children_.end()) { + children_.insert(std::next(it), child); + } + OnInsertChildAfter(child, slibing); + } + + void RemoveAllChild() + { + for (auto it = children_.begin(); it != children_.end();) { + RemoveChild(*it); + } + OnRemoveAllChild(); + } + ArkUI_NodeHandle (*getChildAt)(ArkUI_NodeHandle node, int32_t position); + ArkUI_NodeHandle (*getFirstChild)(ArkUI_NodeHandle node); + ArkUI_NodeHandle (*getLastChild)(ArkUI_NodeHandle node); + ArkUI_NodeHandle (*getPreviousSibling)(ArkUI_NodeHandle node); + ArkUI_NodeHandle (*getNextSibling)(ArkUI_NodeHandle node); + + // 以下方法不可跨过ContentSlot。获取nodeHandle后可根据nativeEntry保存的节点map,做对应查找。 + ArkUI_NodeHandle GetParent() const { return nativeModule_->getParent(handle_); } + ArkUI_NodeHandle GetChildAt(uint32_t index) const { return nativeModule_->getChildAt(handle_, index); } + ArkUI_NodeHandle GetFirstChild() const { return nativeModule_->getFirstChild(handle_); } + ArkUI_NodeHandle GetLastChild() const { return nativeModule_->getLastChild(handle_); } + ArkUI_NodeHandle GetPreviousSibling() const { return nativeModule_->getPreviousSibling(handle_); } + ArkUI_NodeHandle GetNextSibling() const { return nativeModule_->getNextSibling(handle_); } + + // 以下方法可以跨过ContentSlot。 + ArkUI_NodeHandle GetParentInPageTree() const { return OH_ArkUI_NodeUtils_GetParentInPageTree(handle_); } + + ArkUI_NodeHandle GetCurrentPageRootNode() const + { + auto rootNode = OH_ArkUI_NodeUtils_GetCurrentPageRootNode(handle_); + + int32_t uniqueId = -1; + OH_ArkUI_NodeUtils_GetNodeUniqueId(handle_, &uniqueId); + auto nodeType = OH_ArkUI_NodeUtils_GetNodeType(handle_); + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "BaseNode", + "Print base node info, uniqueId%{public}d, type:%{public}d, ", uniqueId, nodeType); + return rootNode; + } + + ArkUI_NodeHandle GetActiveChildrenByIndex(uint32_t index) const + { + ArkUI_ActiveChildrenInfo *childrenInfo; + OH_ArkUI_NodeUtils_GetActiveChildrenInfo(handle_, &childrenInfo); + auto count = OH_ArkUI_ActiveChildrenInfo_GetCount(childrenInfo); + ArkUI_NodeHandle child; + if (index < count) { + child = OH_ArkUI_ActiveChildrenInfo_GetNodeByIndex(childrenInfo, index); + int32_t uniqueId = -1; + OH_ArkUI_NodeUtils_GetNodeUniqueId(child, &uniqueId); + auto nodeType = OH_ArkUI_NodeUtils_GetNodeType(child); + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "BaseNode", + "Print child info, uniqueId%{public}d, type:%{public}d, ", uniqueId, nodeType); + } + OH_ArkUI_ActiveChildrenInfo_Destroy(childrenInfo); + return child; + } + + // 用于获取懒展开的第一个活跃子节点下标。 + uint32_t GetFirstChildIndexWithoutExpand() const + { + uint32_t index = -1; + OH_ArkUI_NodeUtils_GetFirstChildIndexWithoutExpand(handle_, &index); + return index; + } + + // 用于获取懒展开的最后一个活跃子节点下标。 + uint32_t GetLastChildIndexWithoutExpand() const + { + uint32_t index = -1; + OH_ArkUI_NodeUtils_GetLastChildIndexWithoutExpand(handle_, &index); + return index; + } + + // 根据前置接口获取的懒展开活跃节点范围,高效的获取子节点信息。 + ArkUI_NodeHandle GetChildWithExpandMode(uint32_t index) const + { + ArkUI_NodeHandle subNode; + auto result = OH_ArkUI_NodeUtils_GetChildWithExpandMode(handle_, index, &subNode, ARKUI_LAZY_EXPAND); + if (result == ARKUI_ERROR_CODE_NO_ERROR) { + return subNode; + } + return nullptr; + } + + // 通知节点从布局到绘制全部标脏,实际使用可根据业务需要选择其中具体需要执行的内容,提升性能。 + void MarkDirty() + { + nativeModule_->markDirty(handle_, NODE_NEED_MEASURE); + nativeModule_->markDirty(handle_, NODE_NEED_LAYOUT); + nativeModule_->markDirty(handle_, NODE_NEED_RENDER); + } + + // 对单一节点设置单位。 + void SetLengthMetricUnit(ArkUI_LengthMetricUnit unit) { nativeModule_->setLengthMetricUnit(handle_, unit); } + + // 设置及获取自定义属性。 + void AddCustomProperty(const char *name, const char *value) + { + OH_ArkUI_NodeUtils_AddCustomProperty(handle_, name, value); + } + + void RemoveCustomProperty(const char *name) { OH_ArkUI_NodeUtils_RemoveCustomProperty(handle_, name); } + + const char* GetCustomProperty(const char *name) + { + ArkUI_CustomProperty *property; + OH_ArkUI_NodeUtils_GetCustomProperty(handle_, name, &property); + auto value = OH_ArkUI_CustomProperty_GetStringValue(property); + + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "BaseNode", "Get CP name-value: %{public}s - %{public}s", + name, value); + OH_ArkUI_CustomProperty_Destroy(property); + return value; + } + + // 节点迁移,可跨实例转移节点。 + void MoveTo(const std::shared_ptr &anotherParent) + { + OH_ArkUI_NodeUtils_MoveTo(handle_, anotherParent->GetHandle(), -1); //-1代表放到最后一个位置 + } + + ArkUI_NodeHandle GetHandle() const { return handle_; } + + protected: + // 针对父容器子类需要重载下面的函数,实现组件挂载和卸载。 + virtual void OnAddChild(const std::shared_ptr &child) {} + virtual void OnRemoveChild(const std::shared_ptr &child) {} + virtual void OnRemoveAllChild() {} + virtual void OnInsertChild(const std::shared_ptr &child, int32_t index) {} + virtual void OnInsertChildBefore(const std::shared_ptr &child, + const std::shared_ptr &slibing) {} + virtual void OnInsertChildAfter(const std::shared_ptr &child, + const std::shared_ptr &slibing) {} + + ArkUI_NodeHandle handle_; + ArkUI_NativeNodeAPI_1 *nativeModule_ = nullptr; + + private: + std::list> children_; + }; +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUIBASENODE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIColumnNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIColumnNode.h new file mode 100644 index 0000000000000000000000000000000000000000..7d42933850d0272a4b49bfe149f20c4925244c7c --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIColumnNode.h @@ -0,0 +1,33 @@ +/* + * 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. + */ +// ArkUIColumnNode.h +// 自定义绘制组件示例 +#ifndef MYAPPLICATION_ARKUICOLUMNNODE_H +#define MYAPPLICATION_ARKUICOLUMNNODE_H + + +#include "ArkUINode.h" + +namespace NativeModule { + class ArkUIColumnNode : public ArkUINode { + public: + // 使用自定义组件类型ARKUI_NODE_CUSTOM创建组件。 + ArkUIColumnNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_COLUMN)) {} + + ~ArkUIColumnNode() override {} + }; +} // namespace NativeModule +#endif // MYAPPLICATION_ArkUIColumnNode_H diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUICustomContainerNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUICustomContainerNode.h new file mode 100644 index 0000000000000000000000000000000000000000..7c36045d6703c54633e20d71503e55abf7dff060 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUICustomContainerNode.h @@ -0,0 +1,126 @@ +/* + * 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. + */ +// ArkUICustomContainerNode.h +// 自定义容器组件示例 +#ifndef MYAPPLICATION_ARKUICUSTOMCONTAINERNODE_H +#define MYAPPLICATION_ARKUICUSTOMCONTAINERNODE_H + +#include "ArkUINode.h" + +namespace NativeModule { + class ArkUICustomContainerNode : public ArkUINode { + public: + // 使用自定义组件类型ARKUI_NODE_CUSTOM创建组件。 + ArkUICustomContainerNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_CUSTOM)) + { + // 注册自定义事件监听器。 + nativeModule_->addNodeCustomEventReceiver(handle_, OnStaticCustomEvent); + // 声明自定义事件并传递自身作为自定义数据。 + nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, 0, this); + nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, 0, this); + } + + ~ArkUICustomContainerNode() override + { + // 反注册自定义事件监听器。 + nativeModule_->removeNodeCustomEventReceiver(handle_, OnStaticCustomEvent); + // 取消声明自定义事件。 + nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE); + nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT); + } + + void SetPadding(int32_t padding) + { + padding_ = padding; + // 自定义属性事件更新需要主动调用标记脏区接口。 + nativeModule_->markDirty(handle_, NODE_NEED_MEASURE); + } + + private: + static void OnStaticCustomEvent(ArkUI_NodeCustomEvent *event) + { + // 获取组件实例对象,调用相关实例方法。 + auto customNode = reinterpret_cast(OH_ArkUI_NodeCustomEvent_GetUserData(event)); + auto type = OH_ArkUI_NodeCustomEvent_GetEventType(event); + switch (type) { + case ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE: + customNode->OnMeasure(event); + break; + case ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT: + customNode->OnLayout(event); + break; + default: + break; + } + } + + // 自定义测算逻辑。 + void OnMeasure(ArkUI_NodeCustomEvent *event) + { + auto layoutConstrain = OH_ArkUI_NodeCustomEvent_GetLayoutConstraintInMeasure(event); + // 创建子节点布局限制,复用父组件布局中的百分比参考值。 + auto childLayoutConstrain = OH_ArkUI_LayoutConstraint_Copy(layoutConstrain); + int32_t maxConstrain = 1000; + OH_ArkUI_LayoutConstraint_SetMaxHeight(childLayoutConstrain, maxConstrain); + OH_ArkUI_LayoutConstraint_SetMaxWidth(childLayoutConstrain, maxConstrain); + OH_ArkUI_LayoutConstraint_SetMinHeight(childLayoutConstrain, 0); + OH_ArkUI_LayoutConstraint_SetMinWidth(childLayoutConstrain, 0); + + // 测算子节点获取子节点最大值。 + auto totalSize = nativeModule_->getTotalChildCount(handle_); + int32_t maxWidth = 0; + int32_t maxHeight = 0; + for (uint32_t i = 0; i < totalSize; i++) { + auto child = nativeModule_->getChildAt(handle_, i); + // 调用测算接口测算Native组件。 + nativeModule_->measureNode(child, childLayoutConstrain); + auto size = nativeModule_->getMeasuredSize(child); + if (size.width > maxWidth) { + maxWidth = size.width; + } + if (size.height > maxHeight) { + maxHeight = size.height; + } + } + // 自定义测算为所有子节点大小加固定边距。该自定义节点最终的尺寸以此处设置的值为准。 + nativeModule_->setMeasuredSize(handle_, maxWidth + 2 * padding_, maxHeight + 2 * padding_); // padding需要乘以2。 + } + + void OnLayout(ArkUI_NodeCustomEvent *event) + { + // 获取父组件期望位置并设置。 + auto position = OH_ArkUI_NodeCustomEvent_GetPositionInLayout(event); + nativeModule_->setLayoutPosition(handle_, position.x, position.y); + + // 设置子组件居中对齐。 + auto totalSize = nativeModule_->getTotalChildCount(handle_); + auto selfSize = nativeModule_->getMeasuredSize(handle_); + for (uint32_t i = 0; i < totalSize; i++) { + auto child = nativeModule_->getChildAt(handle_, i); + // 获取子组件大小。 + auto childSize = nativeModule_->getMeasuredSize(child); + // 布局子组件位置。 + nativeModule_->layoutNode(child, (selfSize.width - childSize.width) / 2, + (selfSize.height - childSize.height) / 2); // 除以2作居中。 + } + } + + int32_t padding_ = 100; + }; + +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUICUSTOMCONTAINERNODE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUICustomNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUICustomNode.h new file mode 100644 index 0000000000000000000000000000000000000000..bc88a7bc0d7f5078fca319ccb9de81b1d46129a7 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUICustomNode.h @@ -0,0 +1,213 @@ +/* + * 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. + */ +// ArkUICustomNode.h +// 自定义绘制组件示例 +#ifndef MYAPPLICATION_ARKUICUSTOMNODE_H +#define MYAPPLICATION_ARKUICUSTOMNODE_H + +#include +#include +#include + +#include "ArkUINode.h" + +namespace NativeModule { +class ArkUICustomNode : public ArkUINode { +public: + // 使用自定义组件类型ARKUI_NODE_CUSTOM创建组件。 + ArkUICustomNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_CUSTOM)) + { + // 注册自定义事件监听器。 + nativeModule_->addNodeCustomEventReceiver(handle_, OnStaticCustomEvent); + // 声明自定义事件并转递自身作为自定义数据。 + nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_FRONT, 0, this); + nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW, 0, this); + nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND, 0, this); + // 绘制完成事件通知。 + OH_ArkUI_RegisterDrawCallbackOnNodeHandle(handle_, nullptr, [](void* userData) {}); + } + + ~ArkUICustomNode() override + { + // 反注册自定义事件监听器。 + nativeModule_->removeNodeCustomEventReceiver(handle_, OnStaticCustomEvent); + // 取消声明自定义事件。 + nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_FRONT); + nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW); + nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND); + OH_ArkUI_UnregisterDrawCallbackOnNodeHandle(handle_); + } + +private: + int32_t NUM_2 = 2; + int32_t NUM_3 = 3; + int32_t NUM_4 = 4; + int32_t NUM_5 = 5; + + static void OnStaticCustomEvent(ArkUI_NodeCustomEvent *event) + { + // 获取组件实例对象,调用相关实例方法。 + auto targetId = OH_ArkUI_NodeCustomEvent_GetEventTargetId(event); + auto handle = OH_ArkUI_NodeCustomEvent_GetNodeHandle(event); + auto customNode = reinterpret_cast(OH_ArkUI_NodeCustomEvent_GetUserData(event)); + auto type = OH_ArkUI_NodeCustomEvent_GetEventType(event); + switch (type) { + //绘制层级由低到高。 + case ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_BEHIND: + customNode->OnDrawBehind(event); + break; + case ARKUI_NODE_CUSTOM_EVENT_ON_DRAW: + customNode->OnDraw(event); + break; + case ARKUI_NODE_CUSTOM_EVENT_ON_DRAW_FRONT: + customNode->OnDrawFront(event); + break; + case ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW: + customNode->OnDrawForeGround(event); + break; + case ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW: + customNode->OnDrawOverLay(event); + break; + default: + break; + } + } + + // 自定义绘制逻辑。 + void OnDrawBehind(ArkUI_NodeCustomEvent *event) + { + auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event); + // 获取图形绘制对象。 + auto drawCanvas = reinterpret_cast(OH_ArkUI_DrawContext_GetCanvas(drawContext)); + // 获取组件大小。 + auto size = OH_ArkUI_DrawContext_GetSize(drawContext); + // 绘制自定义内容。 + auto path = OH_Drawing_PathCreate(); + OH_Drawing_PathMoveTo(path, size.width / NUM_5, size.height / NUM_5); + OH_Drawing_PathLineTo(path, size.width * NUM_4 / NUM_5, size.height / NUM_5); + OH_Drawing_PathLineTo(path, size.width * NUM_4 / NUM_5, size.height * NUM_4 / NUM_5); + OH_Drawing_PathLineTo(path, size.width / NUM_5, size.height * NUM_4 / NUM_5); + OH_Drawing_PathLineTo(path, size.width / NUM_5, size.height / NUM_5); + OH_Drawing_PathClose(path); + auto brush = OH_Drawing_BrushCreate(); + OH_Drawing_BrushSetColor(brush, 0xFFF0FAFF); // 蓝白色 + OH_Drawing_CanvasAttachBrush(drawCanvas, brush); + OH_Drawing_CanvasDrawPath(drawCanvas, path); + // 释放资源 + OH_Drawing_BrushDestroy(brush); + OH_Drawing_PathDestroy(path); + } + + void OnDraw(ArkUI_NodeCustomEvent *event) + { + auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event); + // 获取图形绘制对象。 + auto drawCanvas = reinterpret_cast(OH_ArkUI_DrawContext_GetCanvas(drawContext)); + // 获取组件大小。 + auto size = OH_ArkUI_DrawContext_GetSize(drawContext); + // 绘制自定义内容。 + auto path = OH_Drawing_PathCreate(); + OH_Drawing_PathMoveTo(path, size.width / NUM_4, size.height / NUM_4); + OH_Drawing_PathLineTo(path, size.width * NUM_3 / NUM_4, size.height / NUM_4); + OH_Drawing_PathLineTo(path, size.width * NUM_3 / NUM_4, size.height * NUM_3 / NUM_4); + OH_Drawing_PathLineTo(path, size.width / NUM_4, size.height * NUM_3 / NUM_4); + OH_Drawing_PathLineTo(path, size.width / NUM_4, size.height / NUM_4); + OH_Drawing_PathClose(path); + auto brush = OH_Drawing_BrushCreate(); + OH_Drawing_BrushSetColor(brush, 0xff2787D9); // 浅蓝色 + OH_Drawing_CanvasAttachBrush(drawCanvas, brush); + OH_Drawing_CanvasDrawPath(drawCanvas, path); + // 释放资源 + OH_Drawing_BrushDestroy(brush); + OH_Drawing_PathDestroy(path); + } + + void OnDrawFront(ArkUI_NodeCustomEvent *event) + { + auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event); + // 获取图形绘制对象。 + auto drawCanvas = reinterpret_cast(OH_ArkUI_DrawContext_GetCanvas(drawContext)); + // 获取组件大小。 + auto size = OH_ArkUI_DrawContext_GetSize(drawContext); + // 绘制自定义内容。 + auto path = OH_Drawing_PathCreate(); + OH_Drawing_PathMoveTo(path, size.width / NUM_3, size.height / NUM_3); + OH_Drawing_PathLineTo(path, size.width * NUM_2 / NUM_3, size.height / NUM_3); + OH_Drawing_PathLineTo(path, size.width * NUM_2 / NUM_3, size.height * NUM_2 / NUM_3); + OH_Drawing_PathLineTo(path, size.width / NUM_3, size.height * NUM_2 / NUM_3); + OH_Drawing_PathLineTo(path, size.width / NUM_3, size.height / NUM_3); + OH_Drawing_PathClose(path); + auto brush = OH_Drawing_BrushCreate(); + OH_Drawing_BrushSetColor(brush, 0xFF004AAF); // 深蓝色 + OH_Drawing_CanvasAttachBrush(drawCanvas, brush); + OH_Drawing_CanvasDrawPath(drawCanvas, path); + // 释放资源 + OH_Drawing_BrushDestroy(brush); + OH_Drawing_PathDestroy(path); + } + + void OnDrawForeGround(ArkUI_NodeCustomEvent *event) + { + auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event); + // 获取图形绘制对象。 + auto drawCanvas = reinterpret_cast(OH_ArkUI_DrawContext_GetCanvas(drawContext)); + // 获取组件大小。 + auto size = OH_ArkUI_DrawContext_GetSize(drawContext); + // 绘制自定义内容。 + auto path = OH_Drawing_PathCreate(); + OH_Drawing_PathMoveTo(path, size.width / NUM_2, size.height / NUM_2); + OH_Drawing_PathLineTo(path, size.width * NUM_2 / NUM_2, size.height / NUM_2); + OH_Drawing_PathLineTo(path, size.width * NUM_2 / NUM_2, size.height * NUM_2 / NUM_2); + OH_Drawing_PathLineTo(path, size.width / NUM_2, size.height * NUM_2 / NUM_2); + OH_Drawing_PathLineTo(path, size.width / NUM_2, size.height / NUM_2); + OH_Drawing_PathClose(path); + auto brush = OH_Drawing_BrushCreate(); + OH_Drawing_BrushSetColor(brush, 0xFFFF0000); // 红色 + OH_Drawing_CanvasAttachBrush(drawCanvas, brush); + OH_Drawing_CanvasDrawPath(drawCanvas, path); + // 释放资源 + OH_Drawing_BrushDestroy(brush); + OH_Drawing_PathDestroy(path); + } + + void OnDrawOverLay(ArkUI_NodeCustomEvent *event) + { + auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event); + // 获取图形绘制对象。 + auto drawCanvas = reinterpret_cast(OH_ArkUI_DrawContext_GetCanvas(drawContext)); + // 获取组件大小。 + auto size = OH_ArkUI_DrawContext_GetSize(drawContext); + // 绘制自定义内容。 + auto path = OH_Drawing_PathCreate(); + OH_Drawing_PathMoveTo(path, size.width, size.height); + OH_Drawing_PathLineTo(path, size.width, size.height); + OH_Drawing_PathLineTo(path, size.width * NUM_2, size.height * NUM_2); + OH_Drawing_PathLineTo(path, size.width, size.height * NUM_2); + OH_Drawing_PathLineTo(path, size.width, size.height / NUM_2); + OH_Drawing_PathClose(path); + auto brush = OH_Drawing_BrushCreate(); + OH_Drawing_BrushSetColor(brush, 0xFF00FF00); // 绿色 + OH_Drawing_CanvasAttachBrush(drawCanvas, brush); + OH_Drawing_CanvasDrawPath(drawCanvas, path); + // 释放资源 + OH_Drawing_BrushDestroy(brush); + OH_Drawing_PathDestroy(path); + } +}; + +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUICUSTOMNODE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemAdapter.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemAdapter.h new file mode 100644 index 0000000000000000000000000000000000000000..0c8caf2ec065dc707383353d57d0c66d08f7e42b --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemAdapter.h @@ -0,0 +1,211 @@ +/* + * 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. + */ +// [Start Lazy_loading_of_text_list] +// ArkUIListItemAdapter +// 用于文本列表懒加载功能代码。 +#ifndef MYAPPLICATION_ARKUILISTITEMADAPTER_H +#define MYAPPLICATION_ARKUILISTITEMADAPTER_H + +#include +#include +#include +#include + +#include "ArkUIListItemNode.h" +#include "ArkUITextNode.h" +#include "NativeModule.h" +#include + +namespace NativeModule { + class ArkUIListItemAdapter { + public: + ArkUIListItemAdapter() + : module_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()), + handle_(OH_ArkUI_NodeAdapter_Create()) // 使用NodeAdapter创建函数。 + { + // 初始化懒加载数据。 + for (int32_t i = 0; i < 1000; i++) { //模拟1000组数据。 + data_.emplace_back(std::to_string(i)); + } + // 设置懒加载数据。 + OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); + // 设置懒加载回调事件。 + OH_ArkUI_NodeAdapter_RegisterEventReceiver(handle_, this, OnStaticAdapterEvent); + } + + ~ArkUIListItemAdapter() + { + // 释放创建的组件。 + while (!cachedItems_.empty()) { + cachedItems_.pop(); + } + items_.clear(); + // 释放Adapter相关资源。 + OH_ArkUI_NodeAdapter_UnregisterEventReceiver(handle_); + OH_ArkUI_NodeAdapter_Dispose(handle_); + } + + ArkUI_NodeAdapterHandle GetHandle() const { return handle_; } + // [Start Remove_Item] + void RemoveItem(int32_t index) + { + // 删除第index个数据。 + data_.erase(data_.begin() + index); + // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件删除元素, + // 根据是否有新增元素回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。 + OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1); + // 更新新的数量。 + OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); + } + // [End Remove_Item] + void InsertItem(int32_t index, const std::string &value) + { + data_.insert(data_.begin() + index, value); + // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID + // 和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件 + // 根据是否有删除元素回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件。 + OH_ArkUI_NodeAdapter_InsertItem(handle_, index, 1); + // 更新新的数量。 + OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); + } + + void MoveItem(int32_t oldIndex, int32_t newIndex) + { + auto temp = data_[oldIndex]; + data_.insert(data_.begin() + newIndex, temp); + data_.erase(data_.begin() + oldIndex); + // 移到位置如果未发生可视区域内元素的可见性变化,则不回调事件,反之根据新增和删除场景回调对应的事件。 + OH_ArkUI_NodeAdapter_MoveItem(handle_, oldIndex, newIndex); + } + + void ReloadItem(int32_t index, const std::string &value) + { + data_[index] = value; + // 如果index位于可视区域内,先回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER删除老元素, + // 再回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。 + OH_ArkUI_NodeAdapter_ReloadItem(handle_, index, 1); + } + + void ReloadAllItem() + { + std::reverse(data_.begin(), data_.end()); + // 全部重新加载场景下,会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID接口获取新的组件ID, + // 根据新的组件ID进行对比,ID不发生变化的进行复用, + // 针对新增ID的元素,调用NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件创建新的组件, + // 然后判断老数据中遗留的未使用ID,调用NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER删除老元素。 + OH_ArkUI_NodeAdapter_ReloadAllItems(handle_); + } + + private: + static void OnStaticAdapterEvent(ArkUI_NodeAdapterEvent *event) + { + // 获取实例对象,回调实例事件。 + auto itemAdapter = reinterpret_cast(OH_ArkUI_NodeAdapterEvent_GetUserData(event)); + itemAdapter->OnAdapterEvent(event); + } + + void OnAdapterEvent(ArkUI_NodeAdapterEvent *event) + { + auto type = OH_ArkUI_NodeAdapterEvent_GetType(event); + switch (type) { + case NODE_ADAPTER_EVENT_ON_GET_NODE_ID: + OnNewItemIdCreated(event); + break; + case NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER: + OnNewItemAttached(event); + break; + case NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER: + OnItemDetached(event); + break; + default: + break; + } + } + + // 分配ID给需要显示的Item,用于ReloadAllItems场景的元素diff。 + void OnNewItemIdCreated(ArkUI_NodeAdapterEvent *event) + { + auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event); + static std::hash hashId = std::hash(); + auto id = hashId(data_[index]); + OH_ArkUI_NodeAdapterEvent_SetNodeId(event, id); + } + + // 需要新的Item显示在可见区域。 + void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) + { + auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event); + ArkUI_NodeHandle handle = OH_ArkUI_NodeAdapterEvent_GetHostNode(event); + + int32_t textHeight = 100; + int32_t textFontSize = 16; + if (!cachedItems_.empty()) { + // 使用并更新回收复用的缓存。 + auto recycledItem = cachedItems_.top(); + auto textItem = std::dynamic_pointer_cast(recycledItem->GetChildren().back()); + handle = recycledItem->GetHandle(); + // 释放缓存池的引用。 + cachedItems_.pop(); + } else { + // 创建新的元素。 + auto listItem = std::make_shared(); + auto textNode = std::make_shared(); + textNode->SetTextContent(data_[index]); + textNode->SetFontSize(textFontSize); + textNode->SetPercentWidth(1); + textNode->SetHeight(textHeight); + textNode->SetBackgroundColor(0xFFfffacd); + textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); + listItem->AddChild(textNode); + auto swipeNode = std::make_shared(); + swipeNode->RegisterOnClick([this, data = data_[index]](ArkUI_NodeEvent *event) { + auto it = std::find(data_.begin(), data_.end(), data); + if (it != data_.end()) { + auto index = std::distance(data_.begin(), it); + RemoveItem(index); + } + }, nullptr); + listItem->SetSwiperAction(swipeNode); + handle = listItem->GetHandle(); + // 保持文本列表项的引用。 + items_.emplace(handle, listItem); + } + // 设置需要展示的元素。 + OH_ArkUI_NodeAdapterEvent_SetItem(event, handle); + } + + // Item从可见区域移除。 + void OnItemDetached(ArkUI_NodeAdapterEvent *event) + { + auto item = OH_ArkUI_NodeAdapterEvent_GetRemovedNode(event); + // 放置到缓存池中进行回收复用。 + cachedItems_.emplace(items_[item]); + } + + std::vector data_; + ArkUI_NativeNodeAPI_1 *module_ = nullptr; + ArkUI_NodeAdapterHandle handle_ = nullptr; + + // 管理NodeAdapter生成的元素。 + std::unordered_map> items_; + + // 管理回收复用组件池。 + std::stack> cachedItems_; + }; + +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUILISTITEMADAPTER_H + // [End Lazy_loading_of_text_list] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemGroupNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemGroupNode.h new file mode 100644 index 0000000000000000000000000000000000000000..cdb28265d1075cb79d1cda8a65a48782a7c86183 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemGroupNode.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + + // [Start Use_grouped_lists] +#ifndef MYAPPLICATION_ARKUILISTITEMGROUPNODE_H +#define MYAPPLICATION_ARKUILISTITEMGROUPNODE_H +#include "ArkUINode.h" +#include "ArkUIListItemAdapter.h" +namespace NativeModule { +class ArkUIListItemGroupNode : public ArkUINode { +public: + ArkUIListItemGroupNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI()) + ->createNode(ARKUI_NODE_LIST_ITEM_GROUP)) {} + void SetHeader(std::shared_ptr node) + { + if (node) { + ArkUI_AttributeItem Item = { .object = node->GetHandle() }; + nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_HEADER, &Item); + } else { + nativeModule_->resetAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_HEADER); + } + } + void SetFooter(std::shared_ptr node) + { + if (node) { + ArkUI_AttributeItem Item = { .object= node->GetHandle() }; + nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_FOOTER, &Item); + } else { + nativeModule_->resetAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_FOOTER); + } + } + std::shared_ptr GetHeader() const + { + return header_; + } + std::shared_ptr GetFooter() const + { + return footer_; + } + //引入懒加载模块。 + void SetLazyAdapter(const std::shared_ptr &adapter) + { + ArkUI_AttributeItem item{nullptr, 0, nullptr, adapter->GetHandle()}; + nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_NODE_ADAPTER, &item); + adapter_ = adapter; + } +private: + std::shared_ptr header_; + std::shared_ptr footer_; + std::shared_ptr adapter_; +}; +} +#endif //MYAPPLICATION_ARKUILISTITEMGROUPNODE_H + // [End Use_grouped_lists] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemNode.h new file mode 100644 index 0000000000000000000000000000000000000000..1225f919d0fcaaaa871f15f03ab4ff14737a1f5f --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListItemNode.h @@ -0,0 +1,56 @@ +/* + * 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. + */ +// [Start Provide_wrapper_class_list_items] +// ArkUIListItemNode.h +// 提供列表项的封装类。 +#ifndef MYAPPLICATION_ARKUILISTITEMNODE_H +#define MYAPPLICATION_ARKUILISTITEMNODE_H +#include "ArkUINode.h" +namespace NativeModule { + class ArkUIListItemNode : public ArkUINode { + public: + ArkUIListItemNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM)) {} + ~ArkUIListItemNode() override + { + if (swipeAction_) { + OH_ArkUI_ListItemSwipeActionOption_Dispose(swipeAction_); + } + if (swipeItem_) { + OH_ArkUI_ListItemSwipeActionItem_Dispose(swipeItem_); + } + } + void SetSwiperAction(std::shared_ptr node) + { + swipeContent_ = node; + swipeItem_ = OH_ArkUI_ListItemSwipeActionItem_Create(); + OH_ArkUI_ListItemSwipeActionItem_SetContent(swipeItem_, node->GetHandle()); + swipeAction_ = OH_ArkUI_ListItemSwipeActionOption_Create(); + OH_ArkUI_ListItemSwipeActionOption_SetEnd(swipeAction_, swipeItem_); + ArkUI_AttributeItem Item = {.object = swipeAction_}; + nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_SWIPE_ACTION, &Item); + } + std::shared_ptr GetSwipeContent() const { return swipeContent_; } + std::list> &GetChildren() { return children_; } + + private: + ArkUI_ListItemSwipeActionOption *swipeAction_ = nullptr; + ArkUI_ListItemSwipeActionItem *swipeItem_ = nullptr; + std::shared_ptr swipeContent_ = nullptr; + std::list> children_; + }; +} // namespace NativeModule +#endif // MYAPPLICATION_ARKUILISTITEMNODE_H +// [End Provide_wrapper_class_list_items] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListNode.h new file mode 100644 index 0000000000000000000000000000000000000000..7a2990f579d82979f99a17b2da89237b39d70fc7 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUIListNode.h @@ -0,0 +1,118 @@ +/* + * 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. + */ +// [Start List_encapsulated_object] +// ArkUIListNode.h +// 提供列表组件的封装。 +#ifndef MYAPPLICATION_ARKUILISTNODE_H +#define MYAPPLICATION_ARKUILISTNODE_H + +#include "ArkUINode.h" +#include "ArkUIListItemAdapter.h" +namespace NativeModule { +class ArkUIListNode : public ArkUINode { +public: + ArkUIListNode() // 创建ArkUI的列表组件。 + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {} + + ~ArkUIListNode() override + { + if (nativeModule_) { + nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX); + } + if (adapter_) { + // 析构的时候卸载adapter下的UI组件。 + nativeModule_->resetAttribute(handle_, NODE_LIST_NODE_ADAPTER); + adapter_.reset(); + } + } + // List组件的属性接口封装。 + void SetScrollBarState(bool isShow) + { + ArkUI_ScrollBarDisplayMode displayMode = + isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF; + ArkUI_NumberValue value[] = {{.i32 = displayMode}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item); + } + + void RegisterOnScrollIndex(const std::function &onScrollIndex) + { + onScrollIndex_ = onScrollIndex; + nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr); + } + // 引入懒加载模块。 + void SetLazyAdapter(const std::shared_ptr &adapter) + { + ArkUI_AttributeItem item{nullptr, 0, nullptr, adapter->GetHandle()}; + nativeModule_->setAttribute(handle_, NODE_LIST_NODE_ADAPTER, &item); + adapter_ = adapter; + } + // [Start ScrollTo] + void ScrollTo(float offset) + { + ArkUI_NumberValue value[] = {{.f32 = 0}, {.f32 = offset}, {.f32 = 0}}; + ArkUI_AttributeItem Item = {.value = value, .size = 3}; + nativeModule_->setAttribute(handle_, NODE_SCROLL_OFFSET, &Item); + } + // [End ScrollTo] + // [Start ScrollToIndex] + void ScrollToIndex(int32_t index) + { + ArkUI_NumberValue value[] = {{.i32 = index}}; + ArkUI_AttributeItem Item = {.value = value, .size = 1}; + nativeModule_->setAttribute(handle_, NODE_LIST_SCROLL_TO_INDEX, &Item); + } + // [End ScrollToIndex] + // [Start ScrollBy] + void ScrollBy(float offset) + { + ArkUI_NumberValue value[] = {{.f32 = 0}, {.f32 = offset}}; + ArkUI_AttributeItem Item = {.value = value, .size = 2}; + nativeModule_->setAttribute(handle_, NODE_SCROLL_BY, &Item); + } + // [End ScrollBy] + // [Start SetSticky] + void SetSticky(ArkUI_StickyStyle style) + { + ArkUI_NumberValue value[] = {{.i32 = style}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_LIST_STICKY, &item); + } +// [End SetSticky] +protected: + void OnNodeEvent(ArkUI_NodeEvent *event) override + { + auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); + switch (eventType) { + case NODE_LIST_ON_SCROLL_INDEX: { + auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0]; + if (onScrollIndex_) { + onScrollIndex_(index.i32); + } + } + default: { + } + } + } + +private: + std::function onScrollIndex_; + + std::shared_ptr adapter_; +}; +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUILISTNODE_H + // [End List_encapsulated_object] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUINode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUINode.h new file mode 100644 index 0000000000000000000000000000000000000000..0c188fba1fb13ea3774143e6101a22e80fb7bcde --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUINode.h @@ -0,0 +1,316 @@ +/* + * 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. + */ +// ArkUINode.h +// 提供通用属性和事件的封装。 +#ifndef MYAPPLICATION_ARKUINODE_H +#define MYAPPLICATION_ARKUINODE_H + +#include "ArkUIBaseNode.h" +#include "NativeModule.h" +#include +#include +#include +#include +#include + +namespace NativeModule { +void CallBack(uint64_t nanoTimeLeft, uint32_t frameCount, void *userData) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "PostCallback", + "***StartCallBack*** nanoTimeLeft = %{public}lu , frameCount = %{public}d", + nanoTimeLeft, frameCount); + if (userData) { + int *myData = (int *)userData; + } + // 执行业务相关逻辑。 +} + +class ArkUINode : public ArkUIBaseNode { +public: + explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) + { + nativeModule_ = NativeModuleInstance::GetInstance()->GetNativeNodeAPI(); + // 事件触发时需要通过函数获取对应的事件对象,这边通过设置节点自定义数据将封装类指针保持在组件上,方便后续事件分发。 + nativeModule_->setUserData(handle_, this); + // 注册节点监听事件接受器。 + nativeModule_->addNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver); + } + + ~ArkUINode() override + { + if (onClick_) { + nativeModule_->unregisterNodeEvent(handle_, NODE_ON_CLICK_EVENT); + } + 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) + { + ArkUI_NumberValue value[] = {{.f32 = width}}; + ArkUI_AttributeItem item = {value, 1}; + auto result = nativeModule_->setAttribute(handle_, NODE_WIDTH, &item); + CheckErrorCode(result); + } + float GetWidth() + { + return nativeModule_->getAttribute(handle_, NODE_WIDTH)->value[0].f32; + } + void SetPercentWidth(float percent) + { + ArkUI_NumberValue value[] = {{.f32 = percent}}; + ArkUI_AttributeItem item = {value, 1}; + auto result = nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item); + CheckErrorCode(result); + } + void SetHeight(float height) + { + ArkUI_NumberValue value[] = {{.f32 = height}}; + ArkUI_AttributeItem item = {value, 1}; + auto result = nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item); + CheckErrorCode(result); + } + float GetHeight() + { + return nativeModule_->getAttribute(handle_, NODE_HEIGHT)->value[0].f32; + } + void SetSize(float width, float height) + { + ArkUI_NumberValue valueWidth[] = {{.f32 = width}}; + ArkUI_AttributeItem itemWidth = {valueWidth, 1}; + nativeModule_->setAttribute(handle_, NODE_WIDTH, &itemWidth); + ArkUI_NumberValue valueHeight[] = {{.f32 = height}}; + ArkUI_AttributeItem itemHeight = {valueHeight, 1}; + nativeModule_->setAttribute(handle_, NODE_HEIGHT, &itemHeight); + } + void SetPercentHeight(float percent) + { + ArkUI_NumberValue value[] = {{.f32 = percent}}; + ArkUI_AttributeItem item = {value, 1}; + auto result = nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item); + CheckErrorCode(result); + } + void SetBackgroundColor(uint32_t color) + { + ArkUI_NumberValue value[] = {{.u32 = color}}; + ArkUI_AttributeItem item = {value, 1}; + auto result = nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item); + CheckErrorCode(result); + } + void SetId(const std::string &id) + { + ArkUI_AttributeItem item = {.string = id.c_str() }; + auto result = nativeModule_->setAttribute(handle_, NODE_ID, &item); + CheckErrorCode(result); + } + void ResetId() { nativeModule_->resetAttribute(handle_, NODE_ID); } + void CheckErrorCode(int32_t errorCode) + { + if (errorCode == ARKUI_ERROR_CODE_NO_ERROR) { + return; + } + int32_t uniqueId = -1; + OH_ArkUI_NodeUtils_GetNodeUniqueId(handle_, &uniqueId); + auto nodeType = OH_ArkUI_NodeUtils_GetNodeType(handle_); + auto isNDKNode = OH_ArkUI_NodeUtils_IsCreatedByNDK(handle_); + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Manager", + "ErrorCode:%{public}d, uniqueId:%{public}d, nodeType:%{public}d, isCreateByNdk:%{public}d", + errorCode, uniqueId, nodeType, isNDKNode); + } + + void SetCrossLanguage(bool isCross) + { + auto option = OH_ArkUI_CrossLanguageOption_Create(); + OH_ArkUI_CrossLanguageOption_SetAttributeSettingStatus(option, isCross); + OH_ArkUI_NodeUtils_SetCrossLanguageOption(handle_, option); + OH_ArkUI_CrossLanguageOption_Destroy(option); + } + + bool GetCrossLanguage() + { + auto option = OH_ArkUI_CrossLanguageOption_Create(); + OH_ArkUI_NodeUtils_GetCrossLanguageOption(handle_, option); + bool isCross = OH_ArkUI_CrossLanguageOption_GetAttributeSettingStatus(option); + int32_t uniqueId = -1; + OH_ArkUI_NodeUtils_GetNodeUniqueId(handle_, &uniqueId); + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Manager", + "uniqueId:%{public}d, isCrossLanguage:%{public}d", uniqueId, isCross); + OH_ArkUI_CrossLanguageOption_Destroy(option); + } + + ArkUI_IntOffset GetLayoutPositionInWindow() + { + ArkUI_IntOffset globalOffset; + auto result = OH_ArkUI_NodeUtils_GetLayoutPositionInWindow(handle_, &globalOffset); + if (result == ARKUI_ERROR_CODE_NO_ERROR) { + return globalOffset; + } else { + return {0, 0}; + } + } + + ArkUI_IntOffset GetPositionWithTranslateInWindow() + { + ArkUI_IntOffset translateOffset; + auto result = OH_ArkUI_NodeUtils_GetPositionWithTranslateInWindow(handle_, &translateOffset); + if (result == ARKUI_ERROR_CODE_NO_ERROR) { + return translateOffset; + } else { + return {0, 0}; + } + } + + // 处理通用事件。 + void RegisterOnClick(const std::function &onClick, void* userData) + { + onClick_ = onClick; + // 注册点击事件。 + nativeModule_->registerNodeEvent(handle_, NODE_ON_CLICK_EVENT, 0, userData); + } + + void RegisterOnTouch(const std::function &onTouch) + { + onTouch_ = onTouch; + // 注册触碰事件。 + nativeModule_->registerNodeEvent(handle_, NODE_TOUCH_EVENT, 0, nullptr); + } + + void RegisterOnDisappear(const std::function &onDisappear) + { + onDisappear_ = onDisappear; + // 注册卸载事件。 + nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR, 0, nullptr); + } + + void RegisterOnAppear(const std::function &onAppear) + { + onAppear_ = onAppear; + // 注册挂载事件。 + nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr); + } + + // 抛出任务在下一帧渲染时执行,用于执行一些需等待其他任务完成时的业务逻辑。 + void PostFrameCallback(void *data) + { + auto context = OH_ArkUI_GetContextByNode(handle_); + OH_ArkUI_PostFrameCallback(context, &data, CallBack); + } + + // 抛出任务在下一帧渲染结束后且vsync信号来临还有大于1ms时执行,若剩余时间小于1ms,则顺延至下一帧并自动请求vysnc。 + void PostIdleCallback(void *data) + { + auto context = OH_ArkUI_GetContextByNode(handle_); + OH_ArkUI_PostIdleCallback(context, &data, CallBack); + } + +protected: + // 组件树操作的实现类对接。 + void OnAddChild(const std::shared_ptr &child) override + { + nativeModule_->addChild(handle_, child->GetHandle()); + } + void OnRemoveChild(const std::shared_ptr &child) override + { + nativeModule_->removeChild(handle_, child->GetHandle()); + } + void OnRemoveAllChild() override + { + nativeModule_->removeAllChildren(handle_); + } + void OnInsertChild(const std::shared_ptr &child, int32_t index) override + { + nativeModule_->insertChildAt(handle_, child->GetHandle(), index); + } + void OnInsertChildBefore(const std::shared_ptr &child, + const std::shared_ptr &slibing) override + { + nativeModule_->insertChildBefore(handle_, child->GetHandle(), slibing->GetHandle()); + } + void OnInsertChildAfter(const std::shared_ptr &child, + const std::shared_ptr &slibing) override + { + nativeModule_->insertChildAfter(handle_, child->GetHandle(), slibing->GetHandle()); + } + + // 事件监听器函数指针。 + static void NodeEventReceiver(ArkUI_NodeEvent *event) + { + // 获取事件发生的UI组件对象。 + auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event); + // 获取保持在UI组件对象中的自定义数据,返回封装类指针。 + auto *node = reinterpret_cast( + NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle)); + // 基于封装类实例对象处理事件。 + node->ProcessNodeEvent(event); + } + void ProcessNodeEvent(ArkUI_NodeEvent *event) + { + auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); + switch (eventType) { + case NODE_ON_CLICK_EVENT: { + if (onClick_) { + onClick_(event); + } + 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: { + // 组件特有事件交给子类处理 + OnNodeEvent(event); + } + } + } + + virtual void OnNodeEvent(ArkUI_NodeEvent *event) {} + +private: + std::function onClick_; + std::function onDisappear_; + std::function onAppear_; + std::function onTouch_; +}; + +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUINODE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUITextInputNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUITextInputNode.h new file mode 100644 index 0000000000000000000000000000000000000000..e9874992b5dea66b995c1e0d458c093055d1cb69 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUITextInputNode.h @@ -0,0 +1,54 @@ +/* + * 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 MYAPPLICATION_ARKUITEXTINPUTNODE_H +#define MYAPPLICATION_ARKUITEXTINPUTNODE_H + +#include "ArkUINode.h" + +#include + +namespace NativeModule { + + class ArkUITextInputNode : public ArkUINode { + public: + ArkUITextInputNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_TEXT_INPUT)) {} + // 文本属性接口封装。 + void SetFontSize(float fontSize) + { + ArkUI_NumberValue value[] = {{.f32 = fontSize}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_FONT_SIZE, &item); + } + void SetFontColor(uint32_t color) + { + ArkUI_NumberValue value[] = {{.u32 = color}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_FONT_COLOR, &item); + } + void SetTextContent(const std::string &content) + { + ArkUI_AttributeItem item = {nullptr, 0, content.c_str()}; + nativeModule_->setAttribute(handle_, NODE_TEXT_INPUT_TEXT, &item); + } + + std::string GetContent() + { + return nativeModule_->getAttribute(handle_, NODE_TEXT_INPUT_TEXT)->string; + } + }; +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUITEXTINPUTNODE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUITextNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUITextNode.h new file mode 100644 index 0000000000000000000000000000000000000000..842dfa08d819cab62547d1793546873551f0929c --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/ArkUITextNode.h @@ -0,0 +1,132 @@ +/* + * 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. + */ +// [Start arkUITestNode_start] +// ArkUITextNode.h +// 实现文本组件的封装类。 +#ifndef MYAPPLICATION_ARKUITEXTNODE_H +#define MYAPPLICATION_ARKUITEXTNODE_H + +#include +#include +#include +#include "ArkUINode.h" +#include +#include "NativeEntry.h" +#include + +namespace NativeModule { + +// 布局完成的回调方法 +void OnLayoutCompleted(void *userData) +{ + ArkUI_NodeHandle node = (ArkUI_NodeHandle)userData; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "the text_node is layout completed"); + ArkUI_NativeNodeAPI_1 *nativeModule = NativeModuleInstance::GetInstance()->GetNativeNodeAPI(); + ArkUI_AttributeItem item = {nullptr, 0, "layout callback"}; + nativeModule->setAttribute(node, NODE_TEXT_CONTENT, &item); +} +// 绘制送显完成的回调方法 +void OnDrawCompleted(void *userData) +{ + ArkUI_NodeHandle node = (ArkUI_NodeHandle)userData; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "the text_node is draw completed"); + ArkUI_NativeNodeAPI_1 *nativeModule = NativeModuleInstance::GetInstance()->GetNativeNodeAPI(); + ArkUI_AttributeItem item = {nullptr, 0, "draw callback"}; + nativeModule->setAttribute(node, NODE_TEXT_CONTENT, &item); +} + +void ColorChangeCallback(ArkUI_SystemColorMode colorMode, void *userData) +{ + if (userData) { + auto handle = (ArkUI_NodeHandle)userData; + // 执行业务相关逻辑,如更换字体颜色,实际所需内容可以根据userData自行修改。 + bool isDark = (colorMode == ARKUI_SYSTEM_COLOR_MODE_DARK); + ArkUI_NumberValue value[] = {{.u32 = isDark ? 0xFFFFFFFF : 0xFF000000}}; // 深色模式字体白色,浅色模式字体黑色。 + ArkUI_AttributeItem item = {value, 1}; + NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(handle, NODE_FONT_COLOR, &item); + } +} + +class ArkUITextNode : public ArkUINode { +public: + ArkUITextNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_TEXT)) {} + // 文本属性接口封装。 + void SetFontSize(float fontSize) + { + ArkUI_NumberValue value[] = {{.f32 = fontSize}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_FONT_SIZE, &item); + } + void SetFontColor(uint32_t color) + { + ArkUI_NumberValue value[] = {{.u32 = color}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_FONT_COLOR, &item); + } + void SetTextContent(const std::string &content) + { + ArkUI_AttributeItem item = {nullptr, 0, content.c_str()}; + nativeModule_->setAttribute(handle_, NODE_TEXT_CONTENT, &item); + } + void SetTextAlign(ArkUI_TextAlignment align) + { + ArkUI_NumberValue value[] = {{.i32 = align}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_TEXT_ALIGN, &item); + } + void SetLayoutCallBack(int32_t nodeId) + { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "set layout callback"); + // 注册布局完成的回调方法 + OH_ArkUI_RegisterLayoutCallbackOnNodeHandle(handle_, this, OnLayoutCompleted); + } + void ResetLayoutCallBack() + { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "reset layout callback"); + // 取消注册布局完成的回调方法 + OH_ArkUI_UnregisterLayoutCallbackOnNodeHandle(handle_); + } + void SetDrawCallBack(int32_t nodeId) + { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "set draw callback"); + // 注册绘制送显完成的回调方法 + OH_ArkUI_RegisterDrawCallbackOnNodeHandle(handle_, this, OnDrawCompleted); + } + void ResetDrawCallBack() + { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "reset draw callback"); + // 取消注册绘制送显完成的回调方法 + OH_ArkUI_UnregisterDrawCallbackOnNodeHandle(handle_); + } + void SetInspectorId(std::string inspectorId) + { + ArkUI_AttributeItem item = {nullptr, 0, inspectorId.c_str()}; + nativeModule_->setAttribute(handle_, NODE_ID, &item); + } + void RegistSystemColorModeChange() + { + OH_ArkUI_RegisterSystemColorModeChangeEvent(handle_, handle_, ColorChangeCallback); + } + + void UnregistSystemColorModeChange() + { + OH_ArkUI_UnregisterSystemColorModeChangeEvent(handle_); + } +}; +} // namespace NativeModule + +#endif // MYAPPLICATION_ARKUITEXTNODE_H +// [End arkUITestNode_start] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/CMakeLists.txt b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..4d1ee407dbee26b9f510c69421a84e0e3cc950ab --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(MyApplication17) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED napi_init.cpp NativeEntry.cpp NormalTextListExample.h ) + +target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so hilog_ndk.z.so) +target_link_libraries(entry PUBLIC libnative_drawing.so) diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/CreateNode.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/CreateNode.h new file mode 100644 index 0000000000000000000000000000000000000000..29cacfa14fb48f18f07a47734c7a6a4e499d0189 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/CreateNode.h @@ -0,0 +1,65 @@ +/* + * 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. + */ +// CreateNode.h +#ifndef MYAPPLICATION_CREATENODE_H +#define MYAPPLICATION_CREATENODE_H + +#include "ArkUINode.h" +#include + +namespace NativeModule { + // 封装Button组件。 + class ArkUIButtonNode : public ArkUINode { + public: + ArkUIButtonNode() + : ArkUINode(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_BUTTON)) {} + int32_t SetLabel(ArkUI_AttributeItem &label_item) + { + return nativeModule_->setAttribute(handle_, NODE_BUTTON_LABEL, &label_item); + } + int32_t SetMargin(ArkUI_AttributeItem &item) + { + return nativeModule_->setAttribute(handle_, NODE_MARGIN, &item); + } + }; + + // 封装Row组件。 + class ArkUIRowNode : public ArkUINode { + public: + ArkUIRowNode() + : ArkUINode(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_ROW)) {} + }; + + // 封装Scroll组件。 + class ArkUIScrollNode : public ArkUINode { + public: + ArkUIScrollNode() + : ArkUINode(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_SCROLL)) {} + }; + + // 封装Column组件。 + class ArkUIColumnNode : public ArkUINode { + public: + ArkUIColumnNode() + : ArkUINode(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_COLUMN)) {} + }; + + // 多线程创建组件。 + napi_value CreateNodeTreeOnMultiThread(napi_env env, napi_callback_info info); + // 释放多线程创建的组件。 + napi_value DisposeNodeTreeOnMultiThread(napi_env env, napi_callback_info info); +} // namespace NativeModule + +#endif // MYAPPLICATION_CREATENODE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/Drawing.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/Drawing.h new file mode 100644 index 0000000000000000000000000000000000000000..6b000af9798c4f7eb5c3daff3d8ef1fd90d0dcf0 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/Drawing.h @@ -0,0 +1,99 @@ +/* + * 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 DRAWING_NATIVEENTRY_H +#define DRAWING_NATIVEENTRY_H +// [Start drawing_start] +#include +#include +#include +#include +#include +#include +#include "common/common.h" + +ArkUI_NodeHandle test_draw(ArkUI_NativeNodeAPI_1 *nodeAPI) +{ + // 创建节点 + // [Start createColumnNode_start] + auto column = nodeAPI->createNode(ARKUI_NODE_COLUMN); + // [End createColumnNode_start] + auto customNode = nodeAPI->createNode(ARKUI_NODE_CUSTOM); + ArkUI_NumberValue value[] = {SIZE_480}; + ArkUI_AttributeItem item = {value, 1}; + // 属性设置 + nodeAPI->setAttribute(column, NODE_WIDTH, &item); + value[0].i32 = SIZE_720; + nodeAPI->setAttribute(column, NODE_HEIGHT, &item); + ArkUI_NumberValue NODE_WIDTH_value[] = {SIZE_200}; + ArkUI_AttributeItem NODE_WIDTH_Item[] = {NODE_WIDTH_value, 1}; + ArkUI_NumberValue NODE_HEIGHT_value[] = {SIZE_200}; + ArkUI_AttributeItem NODE_HEIGHT_Item[] = {NODE_HEIGHT_value, 1}; + ArkUI_NumberValue NODE_BACKGROUND_COLOR_item_value[] = {{.u32 = COLOR_YELLOW}}; + ArkUI_AttributeItem NODE_BACKGROUND_COLOR_Item[] = {NODE_BACKGROUND_COLOR_item_value, 1}; + // [Start userdata_start] + // UserData + struct A { + int32_t a = 6; + bool flag = true; + ArkUI_NodeHandle node; + }; + A *a = new A; + a->node = customNode; + nodeAPI->setAttribute(customNode, NODE_WIDTH, NODE_WIDTH_Item); + nodeAPI->setAttribute(customNode, NODE_HEIGHT, NODE_HEIGHT_Item); + nodeAPI->setAttribute(customNode, NODE_BACKGROUND_COLOR, NODE_BACKGROUND_COLOR_Item); + // 进行事件注册 + nodeAPI->registerNodeCustomEvent(customNode, ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW, 1, a); + // 事件回调函数的编写 + nodeAPI->registerNodeCustomEventReceiver([](ArkUI_NodeCustomEvent *event) { + // 事件回调函数逻辑 + // [End userdata_start] + // 获取自定义事件的相关信息。 + // [Start nodeCustomEvent_start] + auto type = OH_ArkUI_NodeCustomEvent_GetEventType(event); + auto targetId = OH_ArkUI_NodeCustomEvent_GetEventTargetId(event); + auto userData = reinterpret_cast(OH_ArkUI_NodeCustomEvent_GetUserData(event)); + // [End nodeCustomEvent_start] + if (type == ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW && targetId == 1 && userData->flag) { + // [Start drawCanvas_Start] + // 获取自定义事件绘制的上下文。 + auto *drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event); + // 获取绘制canvas指针。 + auto *canvas1 = OH_ArkUI_DrawContext_GetCanvas(drawContext); + // 转换为OH_Drawing_Canvas指针进行绘制。 + OH_Drawing_Canvas *canvas = reinterpret_cast(canvas1); + int32_t width = SIZE_1000; + int32_t height = SIZE_1000; + auto path = OH_Drawing_PathCreate(); + OH_Drawing_PathMoveTo(path, width / SIZE_4, height / SIZE_4); + OH_Drawing_PathLineTo(path, width * SIZE_3 / SIZE_4, height * SIZE_3 / SIZE_4); + OH_Drawing_PathLineTo(path, width * SIZE_3 / SIZE_4, height * SIZE_3 / SIZE_4); + OH_Drawing_PathLineTo(path, width * SIZE_3 / SIZE_4, height * SIZE_3 / SIZE_4); + OH_Drawing_PathLineTo(path, width * SIZE_3 / SIZE_4, height * SIZE_3 / SIZE_4); + OH_Drawing_PathClose(path); + auto pen = OH_Drawing_PenCreate(); + OH_Drawing_PenSetWidth(pen, SIZE_10); + OH_Drawing_PenSetColor(pen, OH_Drawing_ColorSetArgb(RGBA_R1, RGBA_G1, RGBA_B1, RGBA_A1)); + OH_Drawing_CanvasAttachPen(canvas, pen); + OH_Drawing_CanvasDrawPath(canvas, path); + // [End drawCanvas_Start] + } + }); + // 自定义节点上树 + nodeAPI->addChild(column, customNode); + return column; +} +// [End drawing_start] +#endif // DRAWING_NATIVEENTRY_H diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/LazyTextListExample.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/LazyTextListExample.h new file mode 100644 index 0000000000000000000000000000000000000000..840682f2de475026fc537404ff5894321e0152fc --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/LazyTextListExample.h @@ -0,0 +1,55 @@ +/* + * 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. + */ +// [Start Grouped_List_Interface] +// LazyTextListExample.h +// 懒加载列表示例代码。 +#ifndef MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H +#define MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H +#include "ArkUIBaseNode.h" +#include "ArkUIListNode.h" +#include "ArkUIListItemGroupNode.h" +const int HEADER_HEIGHT = 50; +const int HEADER_FONTSIZE = 16; +const int NUM = 3; +namespace NativeModule { +std::shared_ptr CreateLazyTextListExample() +{ +// 创建组件并挂载 + // 1: 创建List组件。 + auto list = std::make_shared(); + list->SetPercentWidth(1); + list->SetPercentHeight(1); + // 设置吸顶 + list->SetSticky(ARKUI_STICKY_STYLE_BOTH); + // 2: 创建ListItemGroup并挂载到List上。 + for (int32_t i = 0; i < NUM; i++) { + auto header = std::make_shared(); + header->SetTextContent("header"); + header->SetFontSize(HEADER_FONTSIZE); + header->SetPercentWidth(1); + header->SetHeight(HEADER_HEIGHT); + header->SetBackgroundColor(0xFFDCDCDC); + header->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); + auto listItemGroup = std::make_shared(); + listItemGroup->SetHeader(header); + auto adapter = std::make_shared(); + listItemGroup->SetLazyAdapter(adapter); + list->AddChild(listItemGroup); + } + return list; +} +} // namespace NativeModule +#endif // MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H +// [End Grouped_List_Interface] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeEntry.cpp b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeEntry.cpp new file mode 100644 index 0000000000000000000000000000000000000000..237b329aa9b7e1292335a75ce79025f548babfff --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeEntry.cpp @@ -0,0 +1,600 @@ +/* + * 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. + */ + +// NativeEntry.cpp +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "NativeEntry.h" +#include "ArkUICustomContainerNode.h" +#include "Drawing.h" +#include +#include +static napi_env g_env = nullptr; +namespace NativeModule { + +#define FRAMEWORK_NODE_TREE_NUMBER 4 // 在框架线程创建组件树的数量。 +#define USER_NODE_TREE_NUMBER 3 // 在开发者线程创建组件树的数量。 +struct AsyncData { + napi_env env; + std::shared_ptr parent = nullptr; + std::shared_ptr child = nullptr; + std::string label = ""; +}; + +// 保存ArkTs侧NodeContent指针与Native侧节点树根节点的对应关系。 +std::map> g_nodeMap; +ArkUI_ContextHandle g_contextHandle = nullptr; + +// 创建组件树。 +void CreateNodeTree(void *asyncUITaskData) +{ + auto asyncData = static_cast(asyncUITaskData); + if (!asyncData) { + return; + } + // 创建组件树根节点。 + auto rowNode = std::make_shared(); + asyncData->child = rowNode; + + // 创建button组件。 + auto buttonNode1 = std::make_shared(); + ArkUI_AttributeItem label_item = {.string = asyncData->label.c_str()}; + // 设置button组件的label属性。 + int32_t result = buttonNode1->SetLabel(label_item); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "Button SetLabel Failed %{public}d", result); + } + ArkUI_NumberValue value[] = {{.f32 = 5}, {.f32 = 5}, {.f32 = 5}, {.f32 = 5}}; + ArkUI_AttributeItem item = {value, 4}; + // 设置button组件的margin属性。 + result = buttonNode1->SetMargin(item); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "Button SetMargin Failed %{public}d", result); + } + int32_t size = 150; + // 设置button组件的width属性。 + buttonNode1->SetWidth(size); + + // 创建button组件。 + auto buttonNode2 = std::make_shared(); + ArkUI_AttributeItem label_item2 = {.string = asyncData->label.c_str()}; + // 设置button组件的label属性。 + result = buttonNode2->SetLabel(label_item2); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "Button SetLabel Failed %{public}d", result); + } + ArkUI_NumberValue value2[] = {{.f32 = 5}, {.f32 = 5}, {.f32 = 5}, {.f32 = 5}}; + ArkUI_AttributeItem item2 = {value2, 4}; + // 设置button组件的margin属性。 + result = buttonNode1->SetMargin(item2); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "Button SetMargin Failed %{public}d", result); + } + // 设置button组件的width属性。 + buttonNode2->SetWidth(size); + + // 把组件挂载到组件树上。 + rowNode->AddChild(buttonNode1); + rowNode->AddChild(buttonNode2); +} + +// 把组件树挂载到UI组件主树上。 +void MountNodeTree(void *asyncUITaskData) +{ + auto asyncData = static_cast(asyncUITaskData); + if (!asyncData) { + return; + } + auto parent = asyncData->parent; + auto child = asyncData->child; + // 把组件树挂载到UI组件主树上。 + parent->AddChild(child); + delete asyncData; +} + +void CreateNodeOnFrameworkThread(ArkUI_ContextHandle contextHandle, std::shared_ptr parent) +{ + for (int i = 0; i < FRAMEWORK_NODE_TREE_NUMBER; i++) { + // UI线程创建子树根节点,保证scroll的子节点顺序。 + auto columnItem = std::make_shared(); + parent->AddChild(columnItem); + AsyncData *asyncData = new AsyncData(); + asyncData->parent = columnItem; + asyncData->label = "OnFwkThread"; + // 使用框架提供的非UI线程创建组件树,创建完成后回到UI线程挂载到主树上。 + int32_t result = OH_ArkUI_PostAsyncUITask(contextHandle, asyncData, CreateNodeTree, MountNodeTree); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_PostAsyncUITask Failed %{public}d", result); + delete asyncData; + } + } +} + +void CreateNodeOnUserThread(ArkUI_ContextHandle contextHandle, std::shared_ptr parent) +{ + auto columnItem = std::make_shared(); + parent->AddChild(columnItem); + // 在开发者创建的非UI线程上创建组件树。 + std::thread userThread([columnItem, contextHandle]() { + for (int i = 0; i < USER_NODE_TREE_NUMBER; i++) { + AsyncData *asyncData = new AsyncData(); + asyncData->parent = columnItem; + asyncData->label = "OnUserThread1"; + CreateNodeTree(asyncData); + // 组件树创建完成后回到UI线程挂载到主树上。 + int32_t result = OH_ArkUI_PostUITask(contextHandle, asyncData, MountNodeTree); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_PostUITask Failed %{public}d", result); + delete asyncData; + } + } + }); + userThread.detach(); +} + +void CreateNodeOnUserThreadAndWait(ArkUI_ContextHandle contextHandle, std::shared_ptr parent) +{ + auto columnItem = std::make_shared(); + parent->AddChild(columnItem); + // 在开发者创建的非UI线程上创建组件树。 + std::thread userThread([columnItem, contextHandle]() { + for (int i = 0; i < USER_NODE_TREE_NUMBER; i++) { + AsyncData *asyncData = new AsyncData(); + asyncData->parent = columnItem; + asyncData->label = "OnUserThread2"; + CreateNodeTree(asyncData); + // 组件树创建完成后回到UI线程挂载到主树上,等待挂载完成后继续创建剩余组件。 + int32_t result = OH_ArkUI_PostUITaskAndWait(contextHandle, asyncData, MountNodeTree); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_PostUITask Failed %{public}d", result); + delete asyncData; + } + } + }); + userThread.detach(); +} + +napi_value CreateNodeTreeOnMultiThread(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = {nullptr, nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + OH_LOG_ERROR(LOG_APP, "kkk OH_ArkUI_GetNodeContentFromNapiValue Failed %{public}d"); + // 获取ArkTs侧组件挂载点。 + ArkUI_NodeContentHandle contentHandle; + int32_t result = OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_GetNodeContentFromNapiValue Failed %{public}d", result); + return nullptr; + } + + // 获取上下文对象指针。 + if (!g_contextHandle) { + result = OH_ArkUI_GetContextFromNapiValue(env, args[1], &g_contextHandle); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_GetContextFromNapiValue Failed %{public}d", result); + delete g_contextHandle; + g_contextHandle = nullptr; + return nullptr; + } + } + + // 创建Native侧组件树根节点。 + auto scrollNode = std::make_shared(); + // 将Native侧组件树根节点挂载到UI主树上。 + result = OH_ArkUI_NodeContent_AddNode(contentHandle, scrollNode->GetHandle()); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_NodeContent_AddNode Failed %{public}d", result); + return nullptr; + } + // 保存Native侧组件树。 + g_nodeMap[contentHandle] = scrollNode; + + auto columnNode = std::make_shared(); + scrollNode->AddChild(columnNode); + // 在框架提供的线程池中创建组件。 + CreateNodeOnFrameworkThread(g_contextHandle, columnNode); + // 在开发者创建的非UI线程中创建组件。 + CreateNodeOnUserThread(g_contextHandle, columnNode); + CreateNodeOnUserThreadAndWait(g_contextHandle, columnNode); + return nullptr; +} + +struct NodeAndContent { + std::shared_ptr node; +}; + +std::shared_ptr CreateCustomPropertyExample() +{ + auto columnNode = std::make_shared(); + float textW = 200; + float testH = 50; + + auto textSave = std::make_shared(); + textSave->SetSize(textW, testH); + textSave->SetTextContent("保存自定义属性"); + auto textRead = std::make_shared(); + textRead->SetSize(textW, testH); + textRead->SetTextContent("读取并打印自定义属性"); + + NodeAndContent* input = new NodeAndContent{ .node = columnNode }; + textSave->RegisterOnClick([](ArkUI_NodeEvent *event) { + auto input = (NodeAndContent *)OH_ArkUI_NodeEvent_GetUserData(event); + input->node->AddCustomProperty("testKey", "testValue"); + }, input); + textRead->RegisterOnClick([](ArkUI_NodeEvent *event) { + auto input = (NodeAndContent *)OH_ArkUI_NodeEvent_GetUserData(event); + auto value = input->node->GetCustomProperty("testKey"); + }, input); + + auto textRoot = std::make_shared(); + textRoot->SetSize(textW, testH); + textRoot->SetTextContent("打印根节点信息"); + textRoot->RegisterOnClick( + [](ArkUI_NodeEvent *event) { + auto input = (NodeAndContent *)OH_ArkUI_NodeEvent_GetUserData(event); + input->node->GetCurrentPageRootNode(); + }, nullptr); + + auto textSearch = std::make_shared(); + textSearch->SetSize(textW, testH); + textSearch->SetTextContent("打印Column的第一个子节点信息"); + textSearch->RegisterOnClick( + [](ArkUI_NodeEvent *event) { + auto input = (NodeAndContent *)OH_ArkUI_NodeEvent_GetUserData(event); + input->node->GetActiveChildrenByIndex(0); + }, nullptr); + + columnNode->AddChild(textSave); + columnNode->AddChild(textRead); + return columnNode; +} + +// 自定义属性Demo +napi_value CreateCustomPropertyDemo(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = {nullptr, nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + // 获取ArkTs侧组件挂载点。 + ArkUI_NodeContentHandle contentHandle; + int32_t result = OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + return nullptr; + } + + // 创建Native侧组件树根节点。 + auto scrollNode = std::make_shared(); + // 将Native侧组件树根节点挂载到UI主树上。 + result = OH_ArkUI_NodeContent_AddNode(contentHandle, scrollNode->GetHandle()); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + return nullptr; + } + // 保存Native侧组件树。 + g_nodeMap[contentHandle] = scrollNode; + + auto columnNode = CreateCustomPropertyExample(); + + scrollNode->AddChild(columnNode); + return nullptr; +} + +std::shared_ptr CreateLazyTextListExample(napi_env env) +{ + // 创建组件并挂载 + // 1:创建List组件。 + auto list = std::make_shared(); + list->SetPercentWidth(1); + list->SetPercentHeight(1); + // 2:创建ListItem懒加载组件并挂载到List上。 + auto adapter = std::make_shared(); + list->SetLazyAdapter(adapter); + return list; +} + +// 懒加载列表示例 +napi_value CreateNodeAdapterDemo(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + // 获取NodeContent + ArkUI_NodeContentHandle contentHandle; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + NativeEntry::GetInstance()->SetContentHandle(contentHandle); + + // 创建懒加载文本列表 + auto node = CreateLazyTextListExample(env); + + // 保持Native侧对象到管理类中,维护生命周期。 + NativeEntry::GetInstance()->SetRootNode(node); + return nullptr; +} + +napi_value DisposeNodeTree(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + // 获取ArkTs侧组件挂载点。 + ArkUI_NodeContentHandle contentHandle; + int32_t result = OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_GetNodeContentFromNapiValue Failed %{public}d", result); + return nullptr; + } + + auto it = g_nodeMap.find(contentHandle); + if (it == g_nodeMap.end()) { + return nullptr; + } + auto rootNode = it->second; + // 将Native侧组件树根节点从UI主树上卸载。 + result = OH_ArkUI_NodeContent_RemoveNode(contentHandle, rootNode->GetHandle()); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_NodeContent_RemoveNode Failed %{public}d", result); + return nullptr; + } + // 释放Native侧组件树。 + g_nodeMap.erase(contentHandle); + return nullptr; +} + +std::shared_ptr CreateTextListExample() +{ + // 创建组件并挂载 + // 1:使用智能指针创建List组件。 + auto list = std::make_shared(); + list->SetPercentWidth(1); + list->SetPercentHeight(1); + list->SetScrollBarState(true); + // 2:创建ListItem子组件并挂载到List上。 + for (int32_t i = 0; i < 30; ++i) { // 创建30个子项目。 + auto listItem = std::make_shared(); + auto textNode = std::make_shared(); + textNode->SetTextContent(std::to_string(i)); + int32_t fontSize = 16; + textNode->SetFontSize(fontSize); + textNode->SetFontColor(0xFFff00ff); + textNode->SetPercentWidth(1); + int32_t width = 300; + int32_t height = 100; + textNode->SetWidth(width); + textNode->SetHeight(height); + textNode->SetBackgroundColor(0xFFfffacd); + textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); + listItem->InsertChild(textNode, i); + list->AddChild(listItem); + } + return list; +} + +// [Start Interface_entrance_mounting_file] +napi_value CreateNativeRoot(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + // 获取NodeContent + ArkUI_NodeContentHandle contentHandle; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + NativeEntry::GetInstance()->SetContentHandle(contentHandle); + //创建文本列表 + auto list = CreateTextListExample(); + //保持Native侧对象到管理类中,维护生命周期。 + NativeEntry::GetInstance()->SetRootNode(list); + return nullptr; +} + +napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) +{ + // 从管理类中释放Native侧对象。 + NativeEntry::GetInstance()->DisposeRootNode(); + return nullptr; +} +// [End Interface_entrance_mounting_file] +napi_value GetContext(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + ArkUI_ContextHandle context = nullptr; + // result 判断是否获取成功 + auto result = OH_ArkUI_GetContextFromNapiValue(env, args[0], &context); + if (result == ARKUI_ERROR_CODE_NO_ERROR) { + NativeEntry::GetInstance()->SetContextHandle(context); + } + return nullptr; +} + +// 通过接口传递TS侧节点信息。 +napi_value GetNodeHandle(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + ArkUI_NodeHandle handle = nullptr; + // result 判断是否获取成功 + auto result = OH_ArkUI_GetNodeHandleFromNapiValue(env, args[0], &handle); + if (result == ARKUI_ERROR_CODE_NO_ERROR) { + NativeEntry::GetInstance()->SetNodeHandle(handle); + } + return nullptr; +} + +// 通过key查询节点 +napi_value GetNodeHandleById(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + size_t maxValueLen = 1024; + char ids[maxValueLen]; + size_t length = 0; + napi_get_value_string_utf8(env, args[0], ids, maxValueLen, &length); + ArkUI_NodeHandle handle = nullptr; + // result 判断是否获取成功 + auto result = OH_ArkUI_NodeUtils_GetAttachedNodeHandleById(ids, &handle); + // 节点获取成功,实现业务功能。 + if (result == ARKUI_ERROR_CODE_NO_ERROR) {} + return nullptr; +} + +// 通过id查询节点 +napi_value GetNodeHandleByUniqueId(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + int32_t id = 0; + napi_get_value_int32(env, args[0], &id); + ArkUI_NodeHandle handle = nullptr; + // result 判断是否获取成功 + auto result = OH_ArkUI_NodeUtils_GetNodeHandleByUniqueId(id, &handle); + if (result == ARKUI_ERROR_CODE_NO_ERROR) { + // 节点获取成功,实现业务功能。 + } +} + +napi_value CreateDrawNode(napi_env env, napi_callback_info info) +{ + size_t argCnt = 1; + int32_t ret; + napi_value args[1] = {nullptr}; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "CreateNativeNode napi_get_cb_info failed"); + } + ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr; + ArkUI_NodeContentHandle nodeContentHandle = nullptr; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle); + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + ArkUI_NodeHandle rootNode = test_draw(nodeAPI); + if (rootNode == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "test_draw_rootNode", "转换NodeContent失败"); + return nullptr; + } + ret = OH_ArkUI_NodeContent_AddNode(nodeContentHandle, rootNode); + if (ret != 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "OH_ArkUI_NodeContent_AddNode_ret", "转换NodeContent失败"); + return nullptr; + } + napi_value exports; + if (napi_create_object(env, &exports) != napi_ok) { + napi_throw_type_error(env, NULL, "napi_create_object failed"); + return nullptr; + } + return exports; +} + +napi_value DisposeNodeTreeOnMultiThread(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + // 获取ArkTs侧组件挂载点。 + ArkUI_NodeContentHandle contentHandle; + int32_t result = OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_GetNodeContentFromNapiValue Failed %{public}d", result); + return nullptr; + } + + auto it = g_nodeMap.find(contentHandle); + if (it == g_nodeMap.end()) { + return nullptr; + } + auto rootNode = it->second; + // 将Native侧组件树根节点从UI主树上卸载。 + result = OH_ArkUI_NodeContent_RemoveNode(contentHandle, rootNode->GetHandle()); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_ERROR(LOG_APP, "OH_ArkUI_NodeContent_RemoveNode Failed %{public}d", result); + return nullptr; + } + // 释放Native侧组件树。 + g_nodeMap.erase(contentHandle); + return nullptr; +} + +// 获取窗口名称 +void NativeEntry::GetWindowName() +{ + ArkUI_HostWindowInfo* windowInfo; + auto result = OH_ArkUI_NodeUtils_GetWindowInfo(nodeHandle_, &windowInfo); + if (result != ARKUI_ERROR_CODE_NO_ERROR) { + return; + } + // 保存窗口名称到全局参数。 + windowName_ = OH_ArkUI_HostWindowInfo_GetName(windowInfo); + // 结构体使用完成后,释放对应内存。 + OH_ArkUI_HostWindowInfo_Destroy(windowInfo); +} + +// 注册事件总线,多次注册会覆盖前置注册的总线,可通过对组件addNodeEventReceiver实现同样效果。 +void NativeEntry::RegisterNodeEventReceiver() +{ + NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->registerNodeEventReceiver([](ArkUI_NodeEvent *event) { + // 从组件事件中获取基础事件对象 + auto *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event); + // 从组件事件获取事件类型 + auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "eventInfo", "inputEvent = %{public}p", inputEvent); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "eventInfo", "eventType = %{public}d", eventType); + auto componentEvent = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event); + // 获取组件事件中的数字类型数据 + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "eventInfo", "componentEvent = %{public}p", componentEvent); + // 获取触发该事件的组件对象 + auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "eventInfo", "nodeHandle = %{public}p", nodeHandle); + // 根据eventType来区分事件类型,进行差异化处理,其他获取事件信息的接口也可类似方式来进行差异化的处理 + switch (eventType) { + case NODE_ON_CLICK_EVENT:{ + //实现具体业务 + break; + } + default:{ + break; + } + } + }); +} + +void NativeEntry::UnregisterNodeEventReceiver() +{ + NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->unregisterNodeEventReceiver(); +} + +} // namespace NativeModule \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeEntry.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeEntry.h new file mode 100644 index 0000000000000000000000000000000000000000..8d75a21cbdbbcf6ef5c088e7a10526ba607d05ac --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeEntry.h @@ -0,0 +1,92 @@ +/* + * 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. + */ +// NativeEntry.h +#ifndef MYAPPLICATION_NATIVEENTRY_H +#define MYAPPLICATION_NATIVEENTRY_H + +#include +#include +#include + +namespace NativeModule { + napi_value CreateNativeRoot(napi_env env, napi_callback_info info); + napi_value CreateNodeTreeOnMultiThread(napi_env env, napi_callback_info info); + napi_value CreateCustomPropertyDemo(napi_env env, napi_callback_info info); + napi_value DisposeNodeTreeOnMultiThread(napi_env env, napi_callback_info info); + napi_value CreateNodeAdapterDemo(napi_env env, napi_callback_info info); + napi_value DisposeNodeTree(napi_env env, napi_callback_info info); + napi_value DestroyNativeRoot(napi_env env, napi_callback_info info); + napi_value GetContext(napi_env env, napi_callback_info info); + napi_value GetNodeHandle(napi_env env, napi_callback_info info); + napi_value GetNodeHandleById(napi_env env, napi_callback_info info); + napi_value GetNodeHandleByUniqueId(napi_env env, napi_callback_info info); + napi_value CreateDrawNode(napi_env env, napi_callback_info info); + napi_value DestroyNativeRoot(napi_env env, napi_callback_info info); + + const unsigned int LOG_PRINT_DOMAIN = 0xFF00; + // 管理Native组件的生命周期和内存。 + class NativeEntry { + public: + static NativeEntry *GetInstance() + { + static NativeEntry nativeEntry; + return &nativeEntry; + } + + void SetContentHandle(ArkUI_NodeContentHandle handle) { handle_ = handle; } + + void SetContextHandle(ArkUI_ContextHandle handle) { context_ = handle; } + + void SetNodeHandle(ArkUI_NodeHandle handle) { nodeHandle_ = handle; } + + void GetWindowName(); + + void SetRootNode(const std::shared_ptr &baseNode) + { + root_ = baseNode; + // 添加Native组件到NodeContent上用于挂载显示。 + OH_ArkUI_NodeContent_AddNode(handle_, root_->GetHandle()); + } + void DisposeRootNode() + { + // 从NodeContent上卸载组件并销毁Native组件。 + OH_ArkUI_NodeContent_RemoveNode(handle_, root_->GetHandle()); + root_.reset(); + } + + void RegisterNodeEventReceiver(); + void UnregisterNodeEventReceiver(); + + void AddNode(std::shared_ptr node) { nodes_.emplace(node->GetHandle(), node); } + std::shared_ptr FindNodeByHandle(ArkUI_NodeHandle nodeHandle) + { + return nodes_.find(nodeHandle)->second; + } + void ClearNode() { nodes_.clear(); } + + private: + std::shared_ptr root_; + ArkUI_NodeContentHandle handle_; + ArkUI_ContextHandle context_; + ArkUI_NodeHandle nodeHandle_; + const char *windowName_ = nullptr; + + // 管理生成的元素,通过map来查找nodeHandle和对应的BaseNode。 + std::unordered_map> nodes_; + }; + +} // namespace NativeModule + +#endif // MYAPPLICATION_NATIVEENTRY_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeModule.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeModule.h new file mode 100644 index 0000000000000000000000000000000000000000..fef93a281063c63d4de85cb9393be2ce5134e385 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NativeModule.h @@ -0,0 +1,52 @@ +/* + * 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. + */ +// NativeModule.h +// 提供获取ArkUI在Native侧模块的封装接口 +#ifndef MYAPPLICATION_NATIVEMODULE_H +#define MYAPPLICATION_NATIVEMODULE_H + +#include "napi/native_api.h" +#include +#include + +#include + +namespace NativeModule { + class NativeModuleInstance { + public: + static NativeModuleInstance *GetInstance() + { + static NativeModuleInstance instance; + return &instance; + } + + NativeModuleInstance() + { + // 获取接口的函数指针结构体对象,用于后续接口调用。 + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, arkUINativeNodeApi_); + // 上下两种获取方式相同,均为获取接口的函数指针结构体对象,用于后续接口调用。 + arkUINativeNodeApi_ = reinterpret_cast( + OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")); + } + // 暴露给其他模块使用。 + ArkUI_NativeNodeAPI_1 *GetNativeNodeAPI() { return arkUINativeNodeApi_; } + + private: + ArkUI_NativeNodeAPI_1 *arkUINativeNodeApi_ = nullptr; + }; + +} // namespace NativeModule + +#endif // MYAPPLICATION_NATIVEMODULE_H \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NormalTextListExample.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NormalTextListExample.h new file mode 100644 index 0000000000000000000000000000000000000000..5035b1800d945e0ffe1b28bc08c17e879583c930 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/NormalTextListExample.h @@ -0,0 +1,60 @@ +/* + * 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. + */ +// [Start normalTextListExample_start] +// NormalTextListExample.h +// 自定义接入入口函数 + +#ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H +#define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H + +#include "ArkUIBaseNode.h" +#include "ArkUIListItemNode.h" +#include "ArkUIListNode.h" +#include "ArkUITextNode.h" +#include "common/common.h" +#include + +namespace NativeModule { + +std::shared_ptr CreateTextListExample() +{ + // 创建组件并挂载 + // 1:使用智能指针创建List组件。 + auto list = std::make_shared(); + list->SetPercentWidth(1); + list->SetPercentHeight(1); + // 2:创建ListItem子组件并挂载到List上。 + for (int32_t i = 0; i < 1; ++i) { + auto listItem = std::make_shared(); + auto textNode = std::make_shared(); + textNode->SetTextContent(std::to_string(i)); + textNode->SetFontSize(SIZE_16); + textNode->SetPercentWidth(1); + textNode->SetHeight(SIZE_100); + textNode->SetBackgroundColor(COLOR_BACKGROUND); + textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); + // 在当前节点注册布局回调 + textNode->SetLayoutCallBack(i); + // 在当前节点注册绘制送显回调 + textNode->SetDrawCallBack(i); + listItem->AddChild(textNode); + list->AddChild(listItem); + } + return list; +} +} // namespace NativeModule + +#endif // MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H +// [End normalTextListExample_start] \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/common/common.h b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/common/common.h new file mode 100644 index 0000000000000000000000000000000000000000..4c02d255a0ae9d25c58e2e766d96dd9c2f30c223 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/common/common.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 NATIVE_EMBEDDED_COMMON_H +#define NATIVE_EMBEDDED_COMMON_H +#define SIZE_3 3 +#define SIZE_4 4 +#define SIZE_16 16 +#define SIZE_10 10 +#define SIZE_30 30 +#define SIZE_100 100 +#define SIZE_200 200 +#define SIZE_480 480 +#define SIZE_720 720 +#define SIZE_1000 1000 + +#define COLOR_YELLOW 0xFFFFFF00 +#define COLOR_BACKGROUND 0xFFfffacd +#define COLOR_BACKGROUND1 0xFFD5D5D5 +#define COLOR_BACKGROUND2 0xFF707070 +#define RGBA_R1 0xFF +#define RGBA_G1 0xFF +#define RGBA_B1 0x00 +#define RGBA_A1 0x00 + +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; + +#endif // NATIVE_EMBEDDED_COMMON_H diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffee421f7bf0a3b7e4cbd13499e7e9e0f84cd4f9 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,65 @@ +/* + * 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. + */ + +// entry/src/main/cpp/napi_init.cpp +#include "napi/native_api.h" +#include "NativeEntry.h" + +static napi_value NAPI_Global_createNativeRoot(napi_env env, napi_callback_info info) {} +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) { + // 绑定Native侧的创建组件和销毁组件。 + napi_property_descriptor desc[] = { + {"createNodeTreeOnMultiThread", nullptr, NativeModule::CreateNodeTreeOnMultiThread, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"createCustomPropertyDemo", nullptr, NativeModule::CreateCustomPropertyDemo, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"createNodeAdapterDemo", nullptr, NativeModule::CreateNodeAdapterDemo, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"disposeNodeTreeOnMultiThread", nullptr, NativeModule::DisposeNodeTreeOnMultiThread, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"disposeNodeTree", nullptr, NativeModule::DisposeNodeTree, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"getContext", nullptr, NativeModule::GetContext, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"getNodeHandle", nullptr, NativeModule::GetNodeHandle, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"getNodeHandleById", nullptr, NativeModule::GetNodeHandleById, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"getNodeHandleByUniqueId", nullptr, NativeModule::GetNodeHandleByUniqueId, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"CreateDrawNode", nullptr, NativeModule::CreateDrawNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"CreateNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"DestroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"createNativeRoot", nullptr, NAPI_Global_createNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr }, + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + 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/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/types/libentry/Index.d.ts b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..4e74c3fb4c42d8132d2b0bb96de578649f550f09 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,16 @@ +import { NodeContent } from "@kit.ArkUI"; + +export const createNativeRoot: (content: Object) => void; +export const createNodeTreeOnMultiThread: (content: Object, context: Object) => void; +export const disposeNodeTreeOnMultiThread: (content: Object) => void; +export const createCustomPropertyDemo: (content: Object) => void; +export const createNodeAdapterDemo: (content: Object) => void; +export const disposeNodeTree: (content: Object) => void; +export const getContext: (context: Object) => void; +export const getNodeHandle: (node: Object) => void; +export const getNodeHandleById: (id: Object) => void; +export const getNodeHandleByUniqueId: (uniqueId: Object) => void; +export const destroyNativeRoot: () => void; +export const CreateDrawNode: (content: NodeContent) => void; +export const CreateNativeRoot: (content: NodeContent) => void; +export const DestroyNativeRoot: () => void; diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/types/libentry/oh-package.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..77052c679533e45a066030a9fc21cdbf9cbcf995 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -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. + */ +{ + "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/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..8f6c151a5febacf5400bfa00a30979eed049b74e --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,61 @@ +/* + * 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 AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import { EnvironmentCallback } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { UIContext } from '@ohos.arkui.UIContext'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + windowStage.loadContent('pages/index', (err, data) => { + if (err.code) { + // window display 拿到屏幕密度 通过storage存到localStorage。 + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +}; diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ce6449f0e91914e73d4502c9f2e8e9a395ea4b1 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,30 @@ +/* + * 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 { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/CustomProperty.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/CustomProperty.ets new file mode 100644 index 0000000000000000000000000000000000000000..8482380b479379e86b819bc7cc8ef28efc5a25e1 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/CustomProperty.ets @@ -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. + */ + +// index.ets +import { NodeContent } from '@kit.ArkUI'; +import entry from 'libentry.so'; + +@Component +struct CAPIComponent { + private rootSlot = new NodeContent(); + + aboutToAppear(): void { + // 页面显示前多线程创建Native组件。 + entry.createCustomPropertyDemo(this.rootSlot); + } + + aboutToDisappear(): void { + // 页面销毁前释放已创建的Native组件。 + entry.disposeNodeTree(this.rootSlot); + } + + build() { + Column() { + // Native组件挂载点。 + ContentSlot(this.rootSlot); + } + } +} + +@Entry +@Component +struct Index { + @State isShow: boolean = false; + @State message: string = 'CreateNodeTree'; + + build() { + Flex() { + Column() { + Text($r('app.string.Common_Interface_Test')) + .fontSize(18) + .fontWeight(FontWeight.Bold) + + CAPIComponent() + }.width('100%') + }.width('100%') + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/EntryComponent.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/EntryComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..3206091e0ba8401b034da1acfc2113a97dfc0b6c --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/EntryComponent.ets @@ -0,0 +1,84 @@ +/* + * 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, UIContext } from '@kit.ArkUI'; +import entry from 'libentry.so'; + +@Component +struct CAPIComponent { + private rootSlot = new NodeContent(); + + aboutToAppear(): void { + // 页面显示前多线程创建Native组件。 + entry.createNodeTreeOnMultiThread(this.rootSlot, this.getUIContext()); + } + + aboutToDisappear(): void { + // 页面销毁前释放已创建的Native组件。 + entry.disposeNodeTree(this.rootSlot); + } + + build() { + Column() { + // Native组件挂载点。 + ContentSlot(this.rootSlot); + } + } +} + +@Entry +@Component +struct Index { + @State isShow: boolean = false; + @State message: string = 'CreateNodeTree'; + + build() { + Flex() { + Column() { + Text('CreateNodeTreeOnMultiThread') + .fontSize(18) + .fontWeight(FontWeight.Bold) + Button(this.message) + .onClick(() => { + this.isShow = !this.isShow; + if (this.isShow) { + this.message = 'DisposeNodeTree' + } else { + this.message = 'CreateNodeTree' + } + }) + if (this.isShow) { + CAPIComponent() + } + Button('ShowDrawPage') + .onClick(() => { + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url: 'pages/drawPage/DrawPage' + }) + }) + Button('ShowNativeUIPage') + .onClick(() => { + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url: 'pages/nativeUI/NativeUIPage' + }) + }) + }.width('100%') + }.width('100%') + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/Index.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a52ba3e443c5ab4217f35c67109098024bccac0 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,110 @@ +/* + * 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,UIContext } from '@kit.ArkUI'; +import entry from 'libentry.so'; + +@Component +struct CAPIComponent { + private rootSlot = new NodeContent(); + + aboutToAppear(): void { + // 页面显示前多线程创建Native组件。 + entry.createNodeTreeOnMultiThread(this.rootSlot, this.getUIContext()); + } + + aboutToDisappear(): void { + // 页面销毁前释放已创建的Native组件。 + entry.disposeNodeTreeOnMultiThread(this.rootSlot); + } + + build() { + Column() { + // Native组件挂载点。 + ContentSlot(this.rootSlot); + } + } +} + +@Entry +@Component +struct Index { + + @State isShow: boolean = false; + @State message: string = 'CreateNodeTree'; + + build() { + Flex() { + Column() { + Text('CreateNodeTreeOnMultiThread') + .fontSize(18) + .fontWeight(FontWeight.Bold) + Button(this.message) + .onClick(() => { + this.isShow = !this.isShow; + if (this.isShow) { + this.message = 'DisposeNodeTree' + } else { + this.message = 'CreateNodeTree' + } + }) + if (this.isShow) { + CAPIComponent() + } + Button('ShowDrawPage') + .onClick(()=>{ + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url:'pages/drawPage/DrawPage' + }) + }) + Button('ShowNativeUIPage') + .onClick(()=>{ + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url:'pages/nativeUI/NativeUIPage' + }) + }) + Button($r('app.string.Create_Component')).onClick(() => { + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url: 'pages/Index' + }); + }) + Button($r('app.string.Custom_Attribute_Test')).onClick(() => { + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url: 'pages/customproperty' + }); + }) + Button($r('app.string.LazyForEach_Page')).onClick(() => { + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url: 'pages/nodeadapter' + }); + }) + // 该接口作用为NDK侧保存主窗口实例,用户保护实例错误调用场景。 + Button($r('app.string.Setting_NDKNativeWindows_Context')).onClick(()=> { + entry.getContext(this.getUIContext()); + }) + }.width('100%') + }.width('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/NodeAdapter.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/NodeAdapter.ets new file mode 100644 index 0000000000000000000000000000000000000000..ada8f72629a9199b0851029d41b10aeef45cadab --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/NodeAdapter.ets @@ -0,0 +1,54 @@ +/* + * 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. + */ + +// index.ets +import { NodeContent } from '@kit.ArkUI'; +import entry from 'libentry.so'; + +@Component +struct CAPIComponent { + private rootSlot = new NodeContent(); + + aboutToAppear(): void { + // 页面显示前多线程创建Native组件。 + entry.createNodeAdapterDemo(this.rootSlot); + } + + build() { + Column() { + // Native组件挂载点。 + ContentSlot(this.rootSlot); + } + } +} + +@Entry +@Component +struct Index { + @State isShow: boolean = false; + @State message: string = 'CreateNodeTree'; + + build() { + Flex() { + Column() { + Text('CreateNodeTreeOnMultiThread') + .fontSize(18) + .fontWeight(FontWeight.Bold) + + CAPIComponent() + }.width('100%') + }.width('100%') + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/drawPage/DrawPage.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/drawPage/DrawPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..dd9b4baf42253db91a066b76cfe47a599a6d782a --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/drawPage/DrawPage.ets @@ -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. + */ + +import render from 'libentry.so'; +import { NodeContent, router } from '@kit.ArkUI'; + +@Entry +@Component +struct DrawPage { + private nodeContent: NodeContent = new NodeContent(); + onPageShow() { + if (render?.CreateDrawNode) { + render.CreateDrawNode(this.nodeContent); + } + } + build() { + Column() { + ContentSlot(this.nodeContent); + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/nativeUI/NativeUIPage.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/nativeUI/NativeUIPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..7a062d69c47545f8383bcdc5d0b3262ba05593bb --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/ets/pages/nativeUI/NativeUIPage.ets @@ -0,0 +1,66 @@ +/* + * 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 render, { DestroyNativeRoot } from 'libentry.so'; +@Entry +@Component + +struct NativeCustomPage { + @State flag:boolean=true; + @State text:string='ShowNativeUI'; + private nodeContent: NodeContent = new NodeContent(); + private isNodeCreated: boolean = true; + onPageShow() { + this.createNativeNodes(); + } + onPageHide() { + this.DestroyNativeRoot(); + } + private createNativeNodes() { + if (render?.CreateNativeRoot && this.isNodeCreated) { + render.CreateNativeRoot(this.nodeContent); + this.isNodeCreated = true; + } + } + private DestroyNativeRoot() { + if (render?.DestroyNativeRoot && !this.isNodeCreated) { + render.DestroyNativeRoot(); + this.isNodeCreated = false; + } + } + build() { + Column() { + Row({ space: 16 }) { + Button('HideNativeUI') + .onClick(()=>{ + this.flag=false; + DestroyNativeRoot(); + }) + } + if(this.flag){ + Column() { + ContentSlot(this.nodeContent); + } + .margin({top:50}) + .flexGrow(1) + .padding(16) + } + } + .width('100%') + .height('100%') + .backgroundColor('#ffffff') + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/module.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c75d702e2d350523978ecaf801c22762ce7d40c0 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/module.json5 @@ -0,0 +1,65 @@ +/* + * 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. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/color.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/float.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/string.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..845c9826206e80d3e4aed8c932a8cf7fa0b9dec3 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,36 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "Create_Component", + "value": "多实例创建组件" + }, + { + "name": "Custom_Attribute_Test", + "value": "自定义属性测试" + }, + { + "name": "LazyForEach_Page", + "value": "懒加载页面" + }, + { + "name": "Setting_NDKNativeWindows_Context", + "value": "设置NDK侧主窗口Context" + }, + { + "name": "Common_Interface_Test", + "value": "通用类接口测试" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/background.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..be4105a540f934fd33ca9d03a5a33407f40eca5d Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/startIcon2.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/startIcon2.png new file mode 100644 index 0000000000000000000000000000000000000000..24bd43eb05e4e5a8b35a3bc9651ec1abbef1ba68 Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/media/startIcon2.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..997638316c475914c9b23cdd80c7f2bd57b8edaf --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,9 @@ +{ + "src": [ + "pages/drawPage/DrawPage", + "pages/nativeUI/NativeUIPage", + "pages/Index", + "pages/CustomProperty", + "pages/NodeAdapter" + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/dark/element/color.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/syscap.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..4fcf7cc73094301809bb72d47cd9857354e6c3dc --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/main/syscap.json @@ -0,0 +1,21 @@ +{ + "devices": { + "general": [ + "default", + "tablet" + ], + "custom": [ + { + "xts": [ + "SystemCapability.ArkUI.ArkUI.Full", + "SystemCapability.ArkUI.ArkUI.Circle", + "SystemCapability.Test.UiTest", + "SystemCapability.Ability.AbilityRuntime.Core", + "SystemCapability.Notification.Emitter", + "SystemCapability.MiscServices.Time", + "SystemCapability.FileManagement.File.FileIO" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/mock/Libentry.mock.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..82fa70b5693ddab96d237d2d17d943d866b61465 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,21 @@ +/* + * 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. + */ +const NativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default NativeMock; \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/mock/mock-config.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..98b0ae79f0090e1fc381d54c959fb32c9f7563f4 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/mock/mock-config.json5 @@ -0,0 +1,19 @@ +/* + * 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. + */ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7f30942b81554a399e89aa253c7089eca4f8d8d1 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/Ability.test.ets @@ -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. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..947b477c9f8b4699515cb45e5eb574a0e77cdfeb --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,24 @@ +/* + * 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 abilityTest from './Ability.test'; +import DrawPageTest from './drawPage/DrawPageTest.test'; +import NativeUIPageTest from './nativeUI/NativeUIPageTest.test'; +import LoadingAdapter from './LoadingAdapter.test'; +export default function testsuite() { + abilityTest(); + DrawPageTest(); + NativeUIPageTest(); + LoadingAdapter() +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/LoadingAdapter.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/LoadingAdapter.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5099ba2f40057bcb7612d9f3dcb3a44faf055ece --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/LoadingAdapter.test.ets @@ -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. + */ + +import { describe, it, expect, beforeAll, Level } from '@ohos/hypium'; +// 导入测试依赖kit +import { abilityDelegatorRegistry, Driver, ON, MouseButton,MatchPattern, UiDirection, On } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Point } from '@ohos.UiTest'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let want: Want; + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let textString: string = await manage.getStringValue(resource); + return textString; +} +export default function IndexTest() { + describe('IndexTest', () => { + beforeAll(async (done: Function) => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + done(); + }) + + /** + * @tc.number UiTest_001 + * @tc.name testLinearGradientEffect + * @tc.desc 点击显示隐藏按钮 + */ + it('testLinearGradientEffect',Level.LEVEL1, async (done: Function) => { + let driver = Driver.create(); + await driver.delayMs(2000); + let openModel = await driver.findComponent(ON.id('Button')); + await openModel.click() + await driver.delayMs(2000) + await driver.pressBack(); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/drawPage/DrawPageTest.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/drawPage/DrawPageTest.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..be00c67ec1fb2ec2a6740ec3c84c7b2653900b87 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/drawPage/DrawPageTest.test.ets @@ -0,0 +1,64 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; + +export default function DrawPageTest() { + describe('DrawPageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + let driver = Driver.create(); + const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + beforeAll(async() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + const want: Want = { + bundleName: 'com.example.nativenodesample', + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(async (done:Function) => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + const driver = Driver.create(); + await driver.pressBack(); + await driver.delayMs(3000); + done(); + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + /** + * @tc.number ArkUIDraw_001 + * @tc.name DrawTest_001 + * @tc.desc 点击显示隐藏按钮 + */ + it('DrawTest_001', 0, async (done:Function) => { + const driver = Driver.create(); + const button = await driver.findComponent(ON.text('ShowDrawPage')); + await button.click(); + await driver.delayMs(3000); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/nativeUI/NativeUIPageTest.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/nativeUI/NativeUIPageTest.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..07d2d0de0ef750d961e46326f4f1c2fde77afcd0 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/ets/test/nativeUI/NativeUIPageTest.test.ets @@ -0,0 +1,66 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; + +export default function NativeUIPageTest() { + describe('NativeUIPageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + let driver = Driver.create(); + const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + beforeAll(async() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + const want: Want = { + bundleName: 'com.example.nativenodesample', + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(async (done:Function) => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + const driver = Driver.create(); + await driver.pressBack(); + await driver.delayMs(1000); + done(); + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + /** + * @tc.number ArkUINativeUI_001 + * @tc.name NativeUITest_001 + * @tc.desc 点击显示隐藏按钮 + */ + it('NativeUIPageTest', 0, async () => { + const driver = Driver.create(); + const button = await driver.findComponent(ON.text('ShowNativeUIPage')); + await button.click(); + await driver.delayMs(1000); + const button1 = await driver.findComponent(ON.text('HideNativeUI')); + await button1.click(); + await driver.delayMs(1000); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/module.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f6bdce9946cb02c0385e5a8836c133c93945013d --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/module.json5 @@ -0,0 +1,26 @@ +/* + * 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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/syscap.json b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..4fcf7cc73094301809bb72d47cd9857354e6c3dc --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/ohosTest/syscap.json @@ -0,0 +1,21 @@ +{ + "devices": { + "general": [ + "default", + "tablet" + ], + "custom": [ + { + "xts": [ + "SystemCapability.ArkUI.ArkUI.Full", + "SystemCapability.ArkUI.ArkUI.Circle", + "SystemCapability.Test.UiTest", + "SystemCapability.Ability.AbilityRuntime.Core", + "SystemCapability.Notification.Emitter", + "SystemCapability.MiscServices.Time", + "SystemCapability.FileManagement.File.FileIO" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/test/List.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..a60c87c5cbb0badf7c3fd8975034590e6fafa992 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * 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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/test/LocalUnit.test.ets b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..841bfd77e56060e50ec0924302a5ae624e76e3aa --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,47 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/hvigor/hvigor-config.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4d435603637cbbfe92ac9865537a0c1051810bb1 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/hvigor/hvigor-config.json5 @@ -0,0 +1,36 @@ +/* + * 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. + */ +{ + "modelVersion": "5.0.5", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/hvigorfile.ts b/ArkUIKit/NativeType/NativeNodeUtilsSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/hvigorfile.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 { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/oh-package.json5 b/ArkUIKit/NativeType/NativeNodeUtilsSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..38abfd099681aeb547cf83a4966111dd5f4f6d13 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * 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. + */ +{ + "modelVersion": "5.0.5", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/ohosTest.md b/ArkUIKit/NativeType/NativeNodeUtilsSample/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..c42970c0f9dce5999b2cd0edaef0387f82635796 --- /dev/null +++ b/ArkUIKit/NativeType/NativeNodeUtilsSample/ohosTest.md @@ -0,0 +1,9 @@ +# NativeNodeSample 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|--------------| -------------- |------------------| ------------------------------------------------------------ | :------- | -------- | +| 示例代码验证 | 设备正常运行 | 输入a、b的值 | 符合预期 | 是 | Pass | +| NativeUI页面示例 | 设备正常运行 | 点击按钮“展示NativeUI页” | 符合预期 | 是 | Pass | +| 绘制页面示例 | 设备正常运行 | 点击按钮"展示绘制页面" | 符合预期 | 是 | Pass | diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/DrawPage.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/DrawPage.png new file mode 100644 index 0000000000000000000000000000000000000000..09f9398f0261b6e8a974be2cabaa02ac8bb1411e Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/DrawPage.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/NativeNode.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/NativeNode.png new file mode 100644 index 0000000000000000000000000000000000000000..3335955bac66745591867168a1e2dc9a0b13a05a Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/NativeNode.png differ diff --git a/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/NativeUI.png b/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/NativeUI.png new file mode 100644 index 0000000000000000000000000000000000000000..b6bd447bfd57a4a3f54ea483165d859f410e9a3f Binary files /dev/null and b/ArkUIKit/NativeType/NativeNodeUtilsSample/screenshots/NativeUI.png differ