diff --git a/ArkUIKit/BuilderNode/AppScope/app.json5 b/ArkUIKit/BuilderNode/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..0f207dea2927536a644282d93e0db8efc2f5ec07 --- /dev/null +++ b/ArkUIKit/BuilderNode/AppScope/app.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. + */ + +{ + "app": { + "bundleName": "com.samples.BuilderNode", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/BuilderNode/AppScope/resources/base/element/string.json b/ArkUIKit/BuilderNode/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/ArkUIKit/BuilderNode/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/ArkUIKit/BuilderNode/AppScope/resources/base/media/background.png b/ArkUIKit/BuilderNode/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/BuilderNode/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/BuilderNode/AppScope/resources/base/media/foreground.png b/ArkUIKit/BuilderNode/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/BuilderNode/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/BuilderNode/AppScope/resources/base/media/layered_image.json b/ArkUIKit/BuilderNode/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/README_zh.md b/ArkUIKit/BuilderNode/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..2fdd937692e9952499245e39abb4fae5249d5d14 --- /dev/null +++ b/ArkUIKit/BuilderNode/README_zh.md @@ -0,0 +1,112 @@ +# ArkUI使用滚动类指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitcode.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [自定义声明式节点 (BuilderNode)](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/arkts-user-defined-arktsNode-builderNode.md)。 + +### 效果预览 + +| EnvironmentCallbackPage | postTouchEvent | inheritFreezeOptionsPage | +|---------------------------|---------------------------|---------------------------| +| ![](pictures/image01.png) | ![](pictures/image02.png) | ![](pictures/image03.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---Common +| |---CommonIndex.ets // 创建NodeController +|---entryability +|---pages +| |---ArkWebPage.ets //BuilderNode结合ArkWeb组件实现预渲染页面 +| |---BuilderProxyNode01.ets //BuilderProxyNode导致树结构发生变化 +| |---BuilderProxyNode02.ets //修复BuilderProxyNode导致树结构发生变化 +| |---EnvironmentCallbackPage.ets //通过系统环境变化更新节点 +| |---FrameNode.ets //创建组件树 +| |---InheritFreezeOptionsPage.ets //设置BuilderNode继承冻结能力 +| |---IsDisposedPage.ets //查询当前BuilderNode是否解除引用 +| |---LocalStoragePage.ets //BuilderNode中使用LocalStorage +| |---PostTouchEvent.ets //注入触摸事件 +| |---RenderNode.ets //BuilderNode与RenderNode结合使用 +| |---ReusablePage01.ets //调用reuse和recycle接口实现节点复用能力 +| |---ReusablePage02.ets //使用@Reusable装饰器 +| |---RouterPage1.ets //跨页面复用 +| |---RouterPage2.ets //跨页面复用 +| |---WrappedBuilder.ets //更新组件树 +entry/src/ohosTest/ +|---ets +| |---ArkWebPage.test.ets // 页面对应测试代码 +| |---BuilderProxyNode01.test.ets // 页面对应测试代码 +| |---BuilderProxyNode02.test.ets // 页面对应测试代码 +| |---EnvironmentCallbackPage.test.ets // 页面对应测试代码 +| |---FrameNode.test.ets // 页面对应测试代码 +| |---InheritFreezeOptionsPage.test.ets // 页面对应测试代码 +| |---IsDisposedPage.test.ets // 页面对应测试代码 +| |---LocalStoragePage.test.ets // 页面对应测试代码 +| |---PostTouchEvent.test.ets // 页面对应测试代码 +| |---RenderNode.test.ets // 页面对应测试代码 +| |---ReusablePage01.test.ets // 页面对应测试代码 +| |---ReusablePage02.test.ets // 页面对应测试代码 +| |---RouterPage.test.ets // 页面对应测试代码 +| |---WrappedBuilder.test.ets // 页面对应测试代码 +``` +### 具体实现 + +一、BuilderNode与NodeController结合实现组件挂载(基础场景) +1. 定义全局@Builder(如buildText):封装需渲染的组件树(如Text、Column),支持传入Params参数; +2. 实现NodeController(如TextNodeController):在makeNode方法中创建BuilderNode实例,调用builderNode.build(wrapBuilder(@Builder), Params)绑定样式与参数,通过getFrameNode()获取根FrameNode并返回; +3. 处理BuilderNode生命周期:可选调用dispose()解除后端实体节点引用,避免内存泄漏。 + +二、BuilderNode组件更新(支持主动更新与系统环境响应) +1. 主动更新:在NodeController中定义update方法,内部调用builderNode.update(新Params),触发组件树重新渲染; +2. 系统环境更新:调用builderNode.updateConfiguration(),监听系统配置变化(如主题、屏幕旋转),触发组件全量更新; +3. 状态绑定:@Builder中引用的自定义组件,需通过@Prop/@ObjectLink绑定状态,确保更新时子组件同步刷新。 + +三、BuilderNode注入触摸事件(postTouchEvent实现事件转发) +1. 定义支持触摸的@Builder(如ButtonBuilder):在@Builder中封装带TapGesture的组件(如Button),处理触摸反馈; +2. NodeController扩展:在NodeController中定义postTouchEvent方法,内部调用builderNode.postTouchEvent(touchEvent),转发触摸事件; +3. 事件转发逻辑:接收触摸事件后,通过postTouchEvent注入BuilderNode对应的组件树,返回值标识事件是否被成功识别。 + +四、BuilderNode结合ArkWeb实现组件预渲染(优化加载效率) +1. 预渲染初始化:在EntryAbility的onWindowStageCreate中,调用createNWeb创建预渲染的BuilderNode,传入UIContext和Web地址,通过WebController调用onActive开启渲染,onFirstMeaningfulPaint后调用onInactive停止预渲染; +2. NodeController管理:myNodeController中通过initWeb方法创建BuilderNode,绑定带ArkWeb的@Builder(webBuilder),makeNode返回预渲染的FrameNode; +3. 预渲染复用:通过Map存储NodeController和WebController,页面调用getNWeb获取预渲染控制器。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行, 支持设备:RK3568。 + +2.本示例为Stage模型,支持API20版本full-SDK,版本号:5.1.0.107,镜像版本号:OpenHarmony_5.1.0 Release。 + +3.本示例需要使用DevEco Studio 5.0.5 Release (Build Version: 5.0.13.200, built on May 13, 2025)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/BuilderNode > .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/BuilderNode/build-profile.json5 b/ArkUIKit/BuilderNode/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4bf5632ff8eaccffcf9a2a7dec209e36ddc3a371 --- /dev/null +++ b/ArkUIKit/BuilderNode/build-profile.json5 @@ -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. + */ + +{ + "app": { + "signingConfigs": [ + + ], + "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" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/code-linter.json5 b/ArkUIKit/BuilderNode/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ed05653cca31b61d64cf6471529eaf50d4f70709 --- /dev/null +++ b/ArkUIKit/BuilderNode/code-linter.json5 @@ -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. + */ + +{ + "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/BuilderNode/entry/build-profile.json5 b/ArkUIKit/BuilderNode/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6bf0d132e6f78049e712446c63f2633b2d1613d3 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/build-profile.json5 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/hvigorfile.ts b/ArkUIKit/BuilderNode/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/hvigorfile.ts @@ -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. + */ + +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/BuilderNode/entry/obfuscation-rules.txt b/ArkUIKit/BuilderNode/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/entry/oh-package.json5 b/ArkUIKit/BuilderNode/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUIKit/BuilderNode/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": {} +} + diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/Common/CommonIndex.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/Common/CommonIndex.ets new file mode 100644 index 0000000000000000000000000000000000000000..d2ca2c8222f46996605ef3a97286ed58d2a004d7 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/Common/CommonIndex.ets @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// 创建NodeController。 +// common.ets +// [Start Common_CommonIndex] +import { UIContext } from '@kit.ArkUI'; +import { webview } from '@kit.ArkWeb'; +import { NodeController, BuilderNode, Size, FrameNode } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +// @Builder中为动态组件的具体组件内容。 +// Data为入参封装类。 +class Data{ + public url: string = ''; + public controller: WebviewController = new webview.WebviewController(); +} +// 通过布尔变量shouldInactive控制网页在后台完成预渲染后停止渲染。 +let shouldInactive: boolean = true; +@Builder +function webBuilder(data:Data) { + Column() { + Web({ src: data.url, controller: data.controller }) + .onPageBegin(() => { + // 调用onActive,开启渲染。 + data.controller.onActive(); + }) + .onFirstMeaningfulPaint(() =>{ + if (!shouldInactive) { + return; + } + // 在预渲染完成时触发,停止渲染。 + data.controller.onInactive(); + shouldInactive = false; + }) + .width('100%') + .height('100%') + } +} +let wrap = wrapBuilder(webBuilder); +// 用于控制和反馈对应的NodeContainer上的节点的行为,需要与NodeContainer一起使用。 +export class MyNodeController2 extends NodeController { + private rootnode: BuilderNode | null = null; + // 必须要重写的方法,用于构建节点数、返回节点挂载在对应NodeContainer中。 + // 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新。 + makeNode(uiContext: UIContext): FrameNode | null { + hilog.info(0xF811, 'testTag', '%{public}s',' uicontext is undefined :' + (uiContext === undefined)); + if (this.rootnode != null) { + // 返回FrameNode节点。 + return this.rootnode.getFrameNode(); + } + // 返回null控制动态组件脱离绑定节点。 + return null; + } + // 当布局大小发生变化时进行回调。 + aboutToResize(size: Size) { + hilog.info(0xF811, 'testTag', '%{public}s','aboutToResize width : ' + size.width + ' height : ' + size.height ); + } + // 当controller对应的NodeContainer在Appear的时候进行回调。 + aboutToAppear() { + hilog.info(0xF811, 'testTag', '%{public}s','aboutToAppear'); + // 切换到前台后,不需要停止渲染。 + shouldInactive = false; + } + // 当controller对应的NodeContainer在Disappear的时候进行回调。 + aboutToDisappear() { + hilog.info(0xF811, 'testTag', '%{public}s','aboutToDisappear'); + } + // 此函数为自定义函数,可作为初始化函数使用。 + // 通过UIContext初始化BuilderNode,再通过BuilderNode中的build接口初始化@Builder中的内容。 + initWeb(url:string, uiContext:UIContext, control:WebviewController) { + if(this.rootnode != null){ + return; + } + // 创建节点,需要uiContext。 + this.rootnode = new BuilderNode(uiContext); + // 创建动态Web组件。 + this.rootnode.build(wrap, { url:url, controller:control }); + } +} +// 创建Map保存所需要的NodeController。 +let nodeMap:Map = new Map(); +// 创建Map保存所需要的WebViewController。 +let controllerMap:Map = new Map(); +// 初始化需要UIContext 需在Ability获取。 +export const createNWeb = (url: string, uiContext: UIContext) => { + // 创建NodeController。 + let baseNode = new MyNodeController2(); + let controller = new webview.WebviewController() ; + // 初始化自定义Web组件。 + baseNode.initWeb(url, uiContext, controller); + controllerMap.set(url, controller); + nodeMap.set(url, baseNode); +} +// 自定义获取NodeController接口。 +export const getNWeb = (url : string) : MyNodeController2 | undefined => { + return nodeMap.get(url); +} +// [End Common_CommonIndex] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..299643d08ef53f51197fa3f16366dfd104771cdf --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/entryability/EntryAbility.ets @@ -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. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { createNWeb } from '../Common/CommonIndex'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/FrameNode', (err) => { + // [Start Web_createNWeb] + createNWeb('', windowStage.getMainWindowSync().getUIContext()); + // [End Web_createNWeb] + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * 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/BuilderNode/entry/src/main/ets/pages/ArkWebPage.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ArkWebPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..d8ff4c498c7bf0bdbee4ac813ea6ae8f264ef453 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ArkWebPage.ets @@ -0,0 +1,39 @@ +/* + * 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. + */ + +// 使用NodeController的Page页。 +// Index.ets +// [Start Main_ArkWebPage] +import { createNWeb, getNWeb } from '../Common/CommonIndex'; + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + // NodeContainer用于与NodeController节点绑定,rebuild会触发makeNode。 + // Page页通过NodeContainer接口绑定NodeController,实现动态组件页面显示。 + NodeContainer(getNWeb('')) + .height('90%') + .width('100%') + .id('ArkWebPage') + } + .width('100%') + } + .height('100%') + } +} +// [End Main_ArkWebPage] diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/BuilderProxyNode01.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/BuilderProxyNode01.ets new file mode 100644 index 0000000000000000000000000000000000000000..2dc49d5de100dc0f39a3b36e1dd6b58b94ed3e2b --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/BuilderProxyNode01.ets @@ -0,0 +1,91 @@ +/* + * 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 Main_BuilderProxyNode01] +import { BuilderNode, typeNode, NodeController, UIContext } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +@Component +struct BlueRowComponent { + build() { + Row() { + Row() { + } + .width('100%') + .height('200vp') + .backgroundColor(0xFF2787D9) + .onTouch((event: TouchEvent) => { + // 触摸绿色Column,蓝色Row的触摸事件不触发 + hilog.info(0xF811, 'testTag', '%{public}s','blue touched: ' + event.type); + }) + } + } +} + +@Component +struct GreenColumnComponent { + build() { + Column() { + } + .id('BuilderProxyNode01') + .width('100%') + .height('100vp') + .backgroundColor(0xFF17A98D) + .hitTestBehavior(HitTestMode.Transparent) + .onTouch((event: TouchEvent) => { + hilog.info(0xF811, 'testTag', '%{public}s','green touched: ' + event.type); + }) + } +} + +@Builder +function buildBlueRow() { + // Builder直接挂载自定义组件,生成BuilderProxyNode + BlueRowComponent() +} + +@Builder +function buildGreenColumn() { + // Builder直接挂载自定义组件,生成BuilderProxyNode + GreenColumnComponent() +} + +class MyNodeController extends NodeController { + makeNode(uiContext: UIContext): FrameNode | null { + const relativeContainer = typeNode.createNode(uiContext, 'RelativeContainer'); + + const blueRowNode = new BuilderNode(uiContext); + blueRowNode.build(wrapBuilder(buildBlueRow)); + + const greenColumnNode = new BuilderNode(uiContext); + greenColumnNode.build(wrapBuilder(buildGreenColumn)); + + // greenColumnNode覆盖在blueRowNode上 + relativeContainer.appendChild(blueRowNode.getFrameNode()); + relativeContainer.appendChild(greenColumnNode.getFrameNode()); + + return relativeContainer; + } +} + +@Entry +@Component +struct BuilderProxyNode01 { + build() { + Column() { + NodeContainer(new MyNodeController()) + } + } +} +// [End Main_BuilderProxyNode01] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/BuilderProxyNode02.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/BuilderProxyNode02.ets new file mode 100644 index 0000000000000000000000000000000000000000..652590ed1e080698aa09a9d6645a46eeef95e501 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/BuilderProxyNode02.ets @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// [Start Main_BuilderProxyNode02] +import { BuilderNode, typeNode, NodeController, UIContext } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +@Component +struct BlueRowComponent { + build() { + Row() { + Row() { + } + .width('100%') + .height('200vp') + .backgroundColor(0xFF2787D9) + .onTouch((event: TouchEvent) => { + // 触摸绿色Column,蓝色Row的触摸事件触发 + hilog.info(0xF811, 'testTag', '%{public}s','blue touched: ' + event.type); + }) + } + } +} + +@Component +struct GreenColumnComponent { + build() { + Column() { + } + .id('BuilderProxyNode02') + .width('100%') + .height('100vp') + .backgroundColor(0xFF17A98D) + .hitTestBehavior(HitTestMode.Transparent) + .onTouch((event: TouchEvent) => { + hilog.info(0xF811, 'testTag', '%{public}s','green touched: ' + event.type); + }) + } +} + +@Builder +function buildBlueRow() { + // Builder直接挂载自定义组件,生成BuilderProxyNode + BlueRowComponent() +} + +@Builder +function buildGreenColumn() { + // Builder根节点为容器组件,不会生成BuilderProxyNode,可以设置属性 + Stack() { + GreenColumnComponent() + } + .hitTestBehavior(HitTestMode.Transparent) +} + +class MyNodeController extends NodeController { + makeNode(uiContext: UIContext): FrameNode | null { + const relativeContainer = typeNode.createNode(uiContext, 'RelativeContainer'); + + const blueRowNode = new BuilderNode(uiContext); + blueRowNode.build(wrapBuilder(buildBlueRow)); + + const greenColumnNode = new BuilderNode(uiContext); + greenColumnNode.build(wrapBuilder(buildGreenColumn)); + + // greenColumnNode覆盖在blueRowNode上 + relativeContainer.appendChild(blueRowNode.getFrameNode()); + relativeContainer.appendChild(greenColumnNode.getFrameNode()); + + return relativeContainer; + } +} + +@Entry +@Component +struct BuilderProxyNode02 { + build() { + Column() { + NodeContainer(new MyNodeController()) + } + } +} +// [End Main_BuilderProxyNode02] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/EnvironmentCallbackPage.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/EnvironmentCallbackPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..f23159ba010fd736645be8f2ad02bebda7f632ab --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/EnvironmentCallbackPage.ets @@ -0,0 +1,150 @@ +/* + * 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 Main_EnvironmentCallbackPage] +import { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI'; +import { AbilityConstant, Configuration, EnvironmentCallback } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +class Params { + public text: string = ''; + + constructor(text: string) { + this.text = text; + } +} + +// 自定义组件 +@Component +struct TextBuilder { + // 作为自定义组件中需要更新的属性,数据类型为基础属性,定义为@Prop + @Prop message: string = 'TextBuilder'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 36 }) + .fontColor($r(`app.color.text_color`)) + .backgroundColor($r(`app.color.start_window_background`)) + } + } + } +} + +@Builder +function buildText(params: Params) { + Column() { + Text(params.text) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 36 }) + .fontColor($r(`app.color.text_color`)) + TextBuilder({ message: params.text }) // 自定义组件 + }.backgroundColor($r(`app.color.start_window_background`)) +} + +class TextNodeController extends NodeController { + private textNode: BuilderNode<[Params]> | null = null; + private message: string = ''; + + constructor(message: string) { + super(); + this.message = message; + } + + makeNode(context: UIContext): FrameNode | null { + return this.textNode?.getFrameNode() ? this.textNode?.getFrameNode() : null; + } + + createNode(context: UIContext) { + this.textNode = new BuilderNode(context); + this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)); + builderNodeMap.push(this.textNode); + } + + deleteNode() { + let node = builderNodeMap.pop(); + node?.dispose(); + } + + update(message: string) { + if (this.textNode !== null) { + // 调用update进行更新。 + this.textNode.update(new Params(message)); + } + } +} + +// 记录创建的自定义节点对象 +const builderNodeMap: BuilderNode<[Params]>[] = []; + +function updateColorMode() { + builderNodeMap.forEach((value, index) => { + // 通知BuilderNode环境变量改变 + value.updateConfiguration(); + }) +} + +@Entry +@Component +struct Index { + @State message: string = 'hello'; + private textNodeController: TextNodeController = new TextNodeController(this.message); + private count = 0; + + aboutToAppear(): void { + let environmentCallback: EnvironmentCallback = { + onMemoryLevel: (level: AbilityConstant.MemoryLevel): void => { + hilog.info(0xF811, 'testTag', '%{public}s','onMemoryLevel'); + }, + onConfigurationUpdated: (config: Configuration): void => { + hilog.info(0xF811, 'testTag', '%{public}s','onConfigurationUpdated ' + JSON.stringify(config)); + updateColorMode(); + } + } + // 注册监听回调 + this.getUIContext().getHostContext()?.getApplicationContext().on('environment', environmentCallback); + //创建自定义节点并添加至map + this.textNodeController.createNode(this.getUIContext()); + } + + aboutToDisappear(): void { + //移除map中的引用,并将自定义节点释放 + this.textNodeController.deleteNode(); + } + + build() { + Row() { + Column() { + NodeContainer(this.textNodeController) + .width('100%') + .height(200) + .backgroundColor('#FFF0F0F0') + Button('Update') + .onClick(() => { + this.count += 1; + const message = 'Update ' + this.count.toString(); + this.textNodeController.update(message); + }) + } + .width('100%') + .height('100%') + } + .height('100%') + } +} +// [End Main_EnvironmentCallbackPage] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/FrameNode.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/FrameNode.ets new file mode 100644 index 0000000000000000000000000000000000000000..5b6a1704b2431fa3e9f2128abe78ecf7e49b174b --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/FrameNode.ets @@ -0,0 +1,81 @@ +/* + * 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 Main_FrameNode] +import { BuilderNode, FrameNode, NodeController, Router, UIContext } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +class Params { + public text: string = ''; + + constructor(text: string) { + this.text = text; + } +} + +@Builder +function buildText(params: Params) { + Column() { + Text(params.text) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 36 }) + } +} + +class TextNodeController extends NodeController { + private textNode: BuilderNode<[Params]> | null = null; + private message: string = 'DEFAULT'; + + constructor(message: string) { + super(); + this.message = message; + } + + makeNode(context: UIContext): FrameNode | null { + this.textNode = new BuilderNode(context); + this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)) + return this.textNode.getFrameNode(); + } +} + +@Entry +@Component +struct FrameNodePage { + @State message: string = 'hello'; + + aboutToAppear() { + try { + let router1 = this.getUIContext().getRouter(); + AppStorage.setOrCreate('router', router1); + } catch (e) { + hilog.info(0xF811, 'testTag', '%{public}s','e' + e); + } + } + + build() { + Row() { + Column() { + NodeContainer(new TextNodeController(this.message)) + .width('100%') + .height(100) + .backgroundColor('#FFF0F0F0') + } + .width('100%') + .height('100%') + } + .height('100%') + } +} +// [End Main_FrameNode] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/InheritFreezeOptionsPage.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/InheritFreezeOptionsPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..289157891496fc8aeb3b35e1f5671a0d496eb18c --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/InheritFreezeOptionsPage.ets @@ -0,0 +1,198 @@ +/* + * 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 Main_InheritFreezeOptionsPage] +import { BuilderNode, FrameNode, NodeController } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +class Params { + public count: number = 0; + + constructor(count: number) { + this.count = count; + } +} + +@Builder +function buildText(params: Params) { + + Column() { + TextBuilder({ message: params.count }) + } +} + +class TextNodeController extends NodeController { + private rootNode: FrameNode | null = null; + private textNode: BuilderNode<[Params]> | null = null; + private count: number = 0; + + makeNode(context: UIContext): FrameNode | null { + this.rootNode = new FrameNode(context); + this.textNode = new BuilderNode(context, { selfIdealSize: { width: 150, height: 150 } }); + this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.count)); + this.textNode.inheritFreezeOptions(true); // 设置BuilderNode的冻结继承状态为true + if (this.rootNode !== null) { + this.rootNode.appendChild(this.textNode.getFrameNode()); // 将BuilderNode上树 + } + return this.rootNode; + } + + update(): void { + if (this.textNode !== null) { + this.count += 1; + this.textNode.update(new Params(this.count)); // 更新BuilderNode中的数据,可以触发Log + } + + } +} + +const textNodeController: TextNodeController = new TextNodeController(); +const ZERO = 0; +@Entry +@Component +struct MyNavigationTestStack { + @Provide('pageInfo') pageInfo: NavPathStack = new NavPathStack(); + @State message: number = ZERO; + @State logNumber: number = ZERO; + + @Builder + PageMap(name: string) { + if (name === 'pageOne') { + pageOneStack({ message: this.message, logNumber: this.logNumber }) + } else if (name === 'pageTwo') { + pageTwoStack({ message: this.message, logNumber: this.logNumber }) + } + } + + build() { + Column() { + Button('update builderNode') // 点击更新BuildrNode + .onClick(() => { + textNodeController.update(); + }) + Navigation(this.pageInfo) { + Column() { + Button('Next Page', { stateEffect: true, type: ButtonType.Capsule }) + .width('80%') + .height(40) + .margin(20) + .onClick(() => { + this.pageInfo.pushPath({ name: 'pageOne' }); // 将name指定的NavDestination页面信息入栈 + }) + } + }.title('NavIndex') + .navDestination(this.PageMap) + .mode(NavigationMode.Stack) + } + } +} + +@Component +struct pageOneStack { + @Consume('pageInfo') pageInfo: NavPathStack; + @State index: number = 1; + @Link message: number; + @Link logNumber: number; + + build() { + NavDestination() { + Column() { + NavigationContentMsgStack({ message: this.message, index: this.index, logNumber: this.logNumber }) + Button('Next Page', { stateEffect: true, type: ButtonType.Capsule }) + .width('80%') + .height(40) + .margin(20) + .onClick(() => { + this.pageInfo.pushPathByName('pageTwo', null); + }) + Button('Back Page', { stateEffect: true, type: ButtonType.Capsule }) + .width('80%') + .height(40) + .margin(20) + .onClick(() => { + this.pageInfo.pop(); + }) + }.width('100%').height('100%') + }.title('pageOne') + .onBackPressed(() => { + this.pageInfo.pop(); + return true; + }) + } +} + +@Component +struct pageTwoStack { + @Consume('pageInfo') pageInfo: NavPathStack; + @State index: number = 2; + @Link message: number; + @Link logNumber: number; + + build() { + NavDestination() { + Column() { + NavigationContentMsgStack({ message: this.message, index: this.index, logNumber: this.logNumber }) + Text('BuilderNode处于冻结') + .fontWeight(FontWeight.Bold) + .margin({ top: 48, bottom: 48 }) + Button('Back Page', { stateEffect: true, type: ButtonType.Capsule }) + .width('80%') + .height(40) + .margin(20) + .onClick(() => { + this.pageInfo.pop(); + }) + }.width('100%').height('100%') + }.title('pageTwo') + .onBackPressed(() => { + this.pageInfo.pop(); + return true; + }) + } +} + +@Component({ freezeWhenInactive: true }) // 设置冻结策略为不活跃冻结 +struct NavigationContentMsgStack { + @Link message: number; + @Link index: number; + @Link logNumber: number; + + build() { + Column() { + if (this.index === 1) { + NodeContainer(textNodeController) + } + } + } +} + +@Component({ freezeWhenInactive: true }) // 设置冻结策略为不活跃冻结 +struct TextBuilder { + @Prop @Watch('info') message: number = 0; + + info(): void { + hilog.info(0xF811, 'testTag', '%{public}s',`freeze-test TextBuilder message callback ${this.message}`); // 根据message内容变化来打印日志来判断是否冻结 + } + + build() { + Row() { + Column() { + Text(`文本更新次数: ${this.message}`) + .fontWeight(FontWeight.Bold) + .margin({ top: 48, bottom: 48 }) + } + } + } +} +// [End Main_InheritFreezeOptionsPage] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/IsDisposedPage.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/IsDisposedPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..b6fc106dc54469236c34abf624cab0f32d3169a8 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/IsDisposedPage.ets @@ -0,0 +1,89 @@ +/* + * 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 Main_IsDisposedPage] +import { NodeController, FrameNode, BuilderNode } from '@kit.ArkUI'; + +@Builder +function buildText() { + Text('Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) +} + +class MyNodeController extends NodeController { + private rootNode: FrameNode | null = null; + private builderNode: BuilderNode<[]> | null = null; + + makeNode(uiContext: UIContext): FrameNode | null { + this.rootNode = new FrameNode(uiContext); + this.rootNode.commonAttribute.width(100) + .height(100) + .backgroundColor(Color.Pink); + this.builderNode = new BuilderNode<[]>(uiContext); + this.builderNode.build(wrapBuilder<[]>(buildText)); + + // 挂载BuilderNode + this.rootNode.appendChild(this.builderNode.getFrameNode()); + return this.rootNode; + } + + disposeBuilderNode() { + // 解除BuilderNode与后端实体节点的引用关系 + this.builderNode?.dispose(); + } + + isDisposed(): string { + if (this.builderNode !== null) { + // 查询BuilderNode是否解除引用 + if (this.builderNode.isDisposed()) { + return 'builderNode isDisposed is true'; + } else { + return 'builderNode isDisposed is false'; + } + } + return 'builderNode is null'; + } +} + +@Entry +@Component +struct Index { + @State text: string = ''; + private myNodeController: MyNodeController = new MyNodeController(); + + build() { + Column({ space: 4 }) { + NodeContainer(this.myNodeController) + Button('BuilderNode dispose') + .onClick(() => { + this.myNodeController.disposeBuilderNode(); + this.text = ''; + }) + .width(200) + .height(50) + Button('BuilderNode isDisposed') + .onClick(() => { + this.text = this.myNodeController.isDisposed(); + }) + .width(200) + .height(50) + Text(this.text) + .fontSize(25) + } + .width('100%') + .height('100%') + } +} +// [End Main_IsDisposedPage] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/LocalStoragePage.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/LocalStoragePage.ets new file mode 100644 index 0000000000000000000000000000000000000000..57acf40706e3e4cc1ece7c003c41d9366689884c --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/LocalStoragePage.ets @@ -0,0 +1,88 @@ +/* + * 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 Main_LocalStoragePage] +import { BuilderNode, NodeController, UIContext } from '@kit.ArkUI'; + +let localStorage1: LocalStorage = new LocalStorage(); +localStorage1.setOrCreate('propA', 'propA'); + +let localStorage2: LocalStorage = new LocalStorage(); +localStorage2.setOrCreate('propB', 'propB'); + +@Entry(localStorage1) +@Component +struct Index { + @LocalStorageLink('propA') propA: string = 'Hello World'; + @State count: number = 0; + private controller: NodeController = new MyNodeController(this.count, localStorage2); + + build() { + Row() { + Column() { + Text(this.propA) + .fontSize(50) + .fontWeight(FontWeight.Bold) + // 使用LocalStorage 实例localStorage2 + Child({ count: this.count }, localStorage2) + NodeContainer(this.controller) + } + .id('LocalStoragePage') + .width('100%') + } + .height('100%') + } +} + +interface Params { + count: number; + localStorage: LocalStorage; +} + +@Builder +function createChild(params: Params) { + //构造过程中传递localStorage + Child({ count: params.count }, params.localStorage) +} + +class MyNodeController extends NodeController { + private count?: number; + private localStorage ?: LocalStorage; + + constructor(count: number, localStorage: LocalStorage) { + super(); + this.count = count; + this.localStorage = localStorage; + } + + makeNode(uiContext: UIContext): FrameNode | null { + let builderNode = new BuilderNode<[Params]>(uiContext); + //构造过程中传递localStorage + builderNode.build(wrapBuilder(createChild), { count: this.count, localStorage: this.localStorage }); + return builderNode.getFrameNode(); + } +} + +@Component +struct Child { + @Prop count: number; + @LocalStorageLink('propB') propB: string = 'Hello World'; + + build() { + Text(this.propB) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } +} +// [End Main_LocalStoragePage] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/PostTouchEvent.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/PostTouchEvent.ets new file mode 100644 index 0000000000000000000000000000000000000000..b99efe0b77baf0644be2ccdcbe16428dad6f1063 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/PostTouchEvent.ets @@ -0,0 +1,87 @@ +/* + * 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 Main_PostTouchEvent] +import { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +class Params { + public text: string = 'this is a text'; +} + +@Builder +function buttonBuilder(params: Params) { + Column() { + Button(`button ` + params.text) + .borderWidth(2) + .backgroundColor(Color.Orange) + .width('100%') + .height('100%') + .gesture( + TapGesture() + .onAction((event: GestureEvent) => { + hilog.info(0xF811, 'testTag', '%{public}s','TapGesture'); + }) + ) + } + .width(500) + .height(300) + .backgroundColor(Color.Gray) +} + +class MyNodeController extends NodeController { + private rootNode: BuilderNode<[Params]> | null = null; + private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder); + + makeNode(uiContext: UIContext): FrameNode | null { + this.rootNode = new BuilderNode(uiContext); + this.rootNode.build(this.wrapBuilder, { text: 'this is a string' }) + return this.rootNode.getFrameNode(); + } + + postTouchEvent(touchEvent: TouchEvent): void { + if (this.rootNode == null) { + return; + } + let result = this.rootNode.postTouchEvent(touchEvent); + hilog.info(0xF811, 'testTag', '%{public}s','result' + result); + } +} + +@Entry +@Component +struct postTouchEventPage { + private nodeController: MyNodeController = new MyNodeController(); + @State bgColor: Color = Color.Pink; + + build() { + Column() { + NodeContainer(this.nodeController) + .height(300) + .width(500) + Column() + .id('onTouch') + .width(500) + .height(300) + .backgroundColor(this.bgColor) + .onTouch((event) => { + if (event != undefined) { + this.nodeController.postTouchEvent(event); + this.bgColor = Color.Blue; + } + }) + } + } +} +// [End Main_PostTouchEvent] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RenderNode.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RenderNode.ets new file mode 100644 index 0000000000000000000000000000000000000000..141724273a87f9b760e480983dd9011178045888 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RenderNode.ets @@ -0,0 +1,83 @@ +/* + * 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 Main_RenderNode] +import { NodeController, BuilderNode, FrameNode, UIContext, RenderNode } from '@kit.ArkUI'; + +class Params { + public text: string = ''; + + constructor(text: string) { + this.text = text; + } +} + +@Builder +function buildText(params: Params) { + Column() { + Text(params.text) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 36 }) + } +} + +class TextNodeController extends NodeController { + private rootNode: FrameNode | null = null; + private textNode: BuilderNode<[Params]> | null = null; + private message: string = 'DEFAULT'; + + constructor(message: string) { + super(); + this.message = message; + } + + makeNode(context: UIContext): FrameNode | null { + this.rootNode = new FrameNode(context); + let renderNode = new RenderNode(); + renderNode.clipToFrame = false; + this.textNode = new BuilderNode(context, { selfIdealSize: { width: 150, height: 150 } }); + this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)); + const textRenderNode = this.textNode?.getFrameNode()?.getRenderNode(); + + const rootRenderNode = this.rootNode.getRenderNode(); + if (rootRenderNode !== null) { + rootRenderNode.appendChild(renderNode); + renderNode.appendChild(textRenderNode); + } + + return this.rootNode; + } +} + +@Entry +@Component +struct RenderNodePage { + @State message: string = 'hello world'; + + build() { + Row() { + Column() { + NodeContainer(new TextNodeController(this.message)) + .width('100%') + .height(100) + .backgroundColor('#FFF0F0F0') + } + .width('100%') + .height('100%') + } + .height('100%') + } +} +// [End Main_RenderNode] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ReusablePage01.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ReusablePage01.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c37b540957d8e0a36f99d53bc3a2025d0d3e371 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ReusablePage01.ets @@ -0,0 +1,192 @@ +/* + * 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 Main_ReusablePage01] +import { FrameNode, NodeController, BuilderNode, UIContext } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const TEST_TAG: string = 'Reuse+Recycle'; + +class MyDataSource { + private dataArray: string[] = []; + private listener: DataChangeListener | null = null; + + public totalCount(): number { + return this.dataArray.length; + } + + public getData(index: number) { + return this.dataArray[index]; + } + + public pushData(data: string) { + this.dataArray.push(data); + } + + public reloadListener(): void { + this.listener?.onDataReloaded(); + } + + public registerDataChangeListener(listener: DataChangeListener): void { + this.listener = listener; + } + + public unregisterDataChangeListener(): void { + this.listener = null; + } +} + +class Params { + public item: string = ''; + + constructor(item: string) { + this.item = item; + } +} + +@Builder +function buildNode(param: Params = new Params('hello')) { + Row() { + Text(`C${param.item} -- `) + ChildComponent2({ item: param.item }) //该自定义组件在BuilderNode中无法被正确复用 + } +} + +class MyNodeController extends NodeController { + public builderNode: BuilderNode<[Params]> | null = null; + public item: string = ''; + + makeNode(uiContext: UIContext): FrameNode | null { + if (this.builderNode == null) { + this.builderNode = new BuilderNode(uiContext, { selfIdealSize: { width: 300, height: 200 } }); + this.builderNode.build(wrapBuilder<[Params]>(buildNode), new Params(this.item)); + } + return this.builderNode.getFrameNode(); + } +} + +// 被回收复用的自定义组件,其状态变量会更新,而子自定义组件ChildComponent3中的状态变量也会更新,但BuilderNode会阻断这一传递过程 +@Reusable +@Component +struct ReusableChildComponent { + @Prop item: string = ''; + @Prop switch: string = ''; + private controller: MyNodeController = new MyNodeController(); + + aboutToAppear() { + this.controller.item = this.item; + } + + aboutToRecycle(): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ReusableChildComponent aboutToRecycle ${this.item}`); + + // 当开关为open,通过BuilderNode的reuse接口和recycle接口传递给其下的自定义组件,例如ChildComponent2,完成复用 + if (this.switch === 'open') { + this.controller?.builderNode?.recycle(); + } + } + + aboutToReuse(params: object): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ReusableChildComponent aboutToReuse ${JSON.stringify(params)}`); + + // 当开关为open,通过BuilderNode的reuse接口和recycle接口传递给其下的自定义组件,例如ChildComponent2,完成复用 + if (this.switch === 'open') { + this.controller?.builderNode?.reuse(params); + } + } + + build() { + Row() { + Text(`A${this.item}--`) + ChildComponent3({ item: this.item }) + NodeContainer(this.controller); + } + } +} + +@Component +struct ChildComponent2 { + @Prop item: string = 'false'; + + aboutToReuse(params: Record) { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ChildComponent2 aboutToReuse ${JSON.stringify(params)}`); + } + + aboutToRecycle(): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ChildComponent2 aboutToRecycle ${this.item}`); + } + + build() { + Row() { + Text(`D${this.item}`) + .fontSize(20) + .backgroundColor(Color.Yellow) + .margin({ left: 10 }) + }.margin({ left: 10, right: 10 }) + } +} + +@Component +struct ChildComponent3 { + @Prop item: string = 'false'; + + aboutToReuse(params: Record) { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ChildComponent3 aboutToReuse ${JSON.stringify(params)}`); + } + + aboutToRecycle(): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ChildComponent3 aboutToRecycle ${this.item}`); + } + + build() { + Row() { + Text(`B${this.item}`) + .fontSize(20) + .backgroundColor(Color.Yellow) + .margin({ left: 10 }) + }.margin({ left: 10, right: 10 }) + } +} + + +@Entry +@Component +struct Index { + @State data: MyDataSource = new MyDataSource(); + + aboutToAppear() { + for (let i = 0; i < 100; i++) { + this.data.pushData(i.toString()); + } + } + + build() { + Column() { + List({ space: 3 }) { + LazyForEach(this.data, (item: string) => { + ListItem() { + ReusableChildComponent({ + item: item, + switch: 'open' // 将open改为close可观察到,BuilderNode不通过reuse和recycle接口传递复用时,BuilderNode内部的自定义组件的行为表现 + }) + } + }, (item: string) => item) + } + .id('List') + .width('100%') + .height('100%') + } + } +} +// [End Main_ReusablePage01] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ReusablePage02.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ReusablePage02.ets new file mode 100644 index 0000000000000000000000000000000000000000..23d372c6911cf9200c9c4b0439af33d51e3c5ef6 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/ReusablePage02.ets @@ -0,0 +1,104 @@ +/* + * 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 Main_ReusablePage02] +import { FrameNode, NodeController, BuilderNode, UIContext } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const TEST_TAG: string = 'Reusable'; + +class Params { + public item: string = ''; + + constructor(item: string) { + this.item = item; + } +} + +@Builder +function buildNode(param: Params = new Params('Hello')) { + ChildComponent2({ item: param.item }) +} + +class MyNodeController extends NodeController { + public builderNode: BuilderNode<[Params]> | null = null; + public item: string = ''; + + constructor(item: string) { + super(); + this.item = item; + } + + makeNode(uiContext: UIContext): FrameNode | null { + if (this.builderNode == null) { + this.builderNode = new BuilderNode(uiContext, { selfIdealSize: { width: 300, height: 200 } }); + this.builderNode.build(wrapBuilder<[Params]>(buildNode), new Params(this.item)); + } + return this.builderNode.getFrameNode(); + } +} + +// 标记了@Reusable的自定义组件,无法直接被BuilderNode挂载为子节点 +@Reusable +@Component +struct ReusableChildComponent { + @Prop item: string = ''; + + aboutToReuse(params: object): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ReusableChildComponent aboutToReuse ${JSON.stringify(params)}`); + } + + aboutToRecycle(): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ReusableChildComponent aboutToRecycle ${this.item}`); + } + + build() { + Text(`A--${this.item}`) + .id('ReusablePage02') + } +} + +// 未标记@Reusable的自定义组件 +@Component +struct ChildComponent2 { + @Prop item: string = ''; + + aboutToReuse(params: Record) { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ChildComponent2 aboutToReuse ${JSON.stringify(params)}`); + } + + aboutToRecycle(): void { + hilog.info(0xF811, 'testTag', '%{public}s',`${TEST_TAG} ChildComponent2 aboutToRecycle ${this.item}`); + } + + build() { + ReusableChildComponent({ item: this.item }) + } +} + + +@Entry +@Component +struct Index { + @State controller: MyNodeController = new MyNodeController('Child'); + + build() { + Column() { + NodeContainer(this.controller) + } + .width('100%') + .height('100%') + } +} +// [End Main_ReusablePage02] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RouterPage1.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RouterPage1.ets new file mode 100644 index 0000000000000000000000000000000000000000..f116bff66f75e7f60fdc3828d424efbe760d053f --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RouterPage1.ets @@ -0,0 +1,102 @@ +/* + * 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. + */ + +// ets/pages/Index.ets +// [Start Main_RouterPage1] +import { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI'; +import 'ets/pages/RouterPage2'; + +@Builder +function buildText() { + // @Builder中使用语法节点生成BuilderProxyNode + if (true) { + MyComponent() + } +} + +@Component +struct MyComponent { + @StorageLink('isShowText') isShowText: boolean = true; + + build() { + if (this.isShowText) { + Column() { + Text('BuilderNode Reuse') + .fontSize(36) + .fontWeight(FontWeight.Bold) + .padding(16) + } + } + } +} + +class TextNodeController extends NodeController { + private rootNode: FrameNode | null = null; + private textNode: BuilderNode<[]> | null = null; + + makeNode(context: UIContext): FrameNode | null { + this.rootNode = new FrameNode(context); + + if (AppStorage.has('textNode')) { + // 复用AppStorage中的BuilderNode + this.textNode = AppStorage.get>('textNode') as BuilderNode<[]>; + const parent = this.textNode.getFrameNode()?.getParent(); + if (parent) { + parent.removeChild(this.textNode.getFrameNode()); + } + } else { + this.textNode = new BuilderNode(context); + this.textNode.build(wrapBuilder<[]>(buildText)); + // 将创建的BuilderNode存入AppStorage + AppStorage.setOrCreate>('textNode', this.textNode); + } + this.rootNode.appendChild(this.textNode.getFrameNode()); + + return this.rootNode; + } +} + +@Entry({ routeName: 'myIndex' }) +@Component +struct Index { + aboutToAppear(): void { + AppStorage.setOrCreate('isShowText', true); + } + + build() { + Row() { + Column() { + NodeContainer(new TextNodeController()) + .width('100%') + .backgroundColor('#FFF0F0F0') + Button('Router pageTwo') + .onClick(() => { + // 改变AppStorage中的状态变量触发Text节点的重新创建 + AppStorage.setOrCreate('isShowText', false); + // 将BuilderNode从AppStorage中移除 + AppStorage.delete('textNode'); + + this.getUIContext().getRouter().replaceNamedRoute({ name: 'pageTwo' }); + }) + .margin({ top: 16 }) + } + .width('100%') + .height('100%') + .padding(16) + } + .height('100%') + } +} +// [End Main_RouterPage1] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RouterPage2.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RouterPage2.ets new file mode 100644 index 0000000000000000000000000000000000000000..311ed486862e1c6a8ec3ffd096ecdf5b71fe2028 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/RouterPage2.ets @@ -0,0 +1,37 @@ +/* + * 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. + */ + +// ets/pages/PageTwo.ets +// 该页面中存在一个按钮,可跳转回主页面,回到主页面后,原有的文字消失 +// [Start Main_RouterPage2] +import 'ets/pages/RouterPage1'; + +@Entry({ routeName: 'pageTwo' }) +@Component +struct PageTwo { + build() { + Column() { + Button('Router replace to index') + .onClick(() => { + this.getUIContext().getRouter().replaceNamedRoute({ name: 'myIndex' }); + }) + } + .height('100%') + .width('100%') + .alignItems(HorizontalAlign.Center) + .padding(16) + } +} +// [End Main_RouterPage2] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/ets/pages/WrappedBuilder.ets b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/WrappedBuilder.ets new file mode 100644 index 0000000000000000000000000000000000000000..1c6885dbb59c983024a6b96c26b53947033c20e7 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/ets/pages/WrappedBuilder.ets @@ -0,0 +1,105 @@ +/* + * 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 Main_WrappedBuilder] +import { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI'; + +class Params { + public text: string = ''; + constructor(text: string) { + this.text = text; + } +} + +// 自定义组件 +@Component +struct TextBuilder { + // 作为自定义组件中需要更新的属性,数据类型为基础属性,定义为@Prop + @Prop message: string = 'TextBuilder'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 36 }) + .backgroundColor(Color.Gray) + } + } + } +} + +@Builder +function buildText(params: Params) { + Column() { + Text(params.text) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 36 }) + TextBuilder({ message: params.text }) // 自定义组件 + } +} + +class TextNodeController extends NodeController { + private textNode: BuilderNode<[Params]> | null = null; + private message: string = ''; + + constructor(message: string) { + super() + this.message = message + } + + makeNode(context: UIContext): FrameNode | null { + this.textNode = new BuilderNode(context); + this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message)) + return this.textNode.getFrameNode(); + } + + update(message: string) { + if (this.textNode !== null) { + // 调用update进行更新。 + this.textNode.update(new Params(message)); + } + } +} + +@Entry +@Component +struct WrappedBuilderPage { + @State message: string = 'hello'; + private textNodeController: TextNodeController = new TextNodeController(this.message); + private count = 0; + + build() { + Row() { + Column() { + NodeContainer(this.textNodeController) + .width('100%') + .height(200) + .backgroundColor('#FFF0F0F0') + Button('Update') + .onClick(() => { + this.count += 1; + const message = 'Update' + this.count.toString(); + this.textNodeController.update(message); + }) + } + .width('100%') + .height('100%') + } + .height('100%') + } +} +// [End Main_WrappedBuilder] \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/module.json5 b/ArkUIKit/BuilderNode/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..25148c9e0e582c3ed037ae97ca8fad095ec7adb8 --- /dev/null +++ b/ArkUIKit/BuilderNode/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": [ + "phone" + ], + "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": [ + "ohos.want.action.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/BuilderNode/entry/src/main/resources/base/element/color.json b/ArkUIKit/BuilderNode/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/entry/src/main/resources/base/element/float.json b/ArkUIKit/BuilderNode/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/entry/src/main/resources/base/element/string.json b/ArkUIKit/BuilderNode/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/background.png b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/BuilderNode/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/BuilderNode/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/BuilderNode/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/BuilderNode/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..93ed6148c33d0327da325fd7e35f7f50a7a67906 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,19 @@ +{ + "src": [ + "pages/FrameNode", + "pages/RenderNode", + "pages/WrappedBuilder", + "pages/PostTouchEvent", + "pages/BuilderProxyNode01", + "pages/BuilderProxyNode02", + "pages/ReusablePage01", + "pages/ReusablePage02", + "pages/EnvironmentCallbackPage", + "pages/RouterPage1", + "pages/RouterPage2", + "pages/LocalStoragePage", + "pages/IsDisposedPage", + "pages/InheritFreezeOptionsPage", + "pages/ArkWebPage" + ] +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/main/resources/dark/element/color.json b/ArkUIKit/BuilderNode/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/BuilderNode/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/BuilderNode/entry/src/ohosTest/ets/test/ArkWebPage.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ArkWebPage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..03c4c589cbaa7ebb1ef67274d6dbd25d0a3671d7 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ArkWebPage.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function ArkWebPageTest() { + describe('ArkWebPageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','ArkWebPageTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/ArkWebPage', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get ArkWebPage state pages:' + JSON.stringify(pages)); + if (!('ArkWebPage' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get ArkWebPage pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push ArkWebPage page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','ArkWebPage beforeEach end'); + }); + + it('ArkWebPageTest', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: ArkWebPageTest begin'); + let driver = Driver.create(); + let componentButton1 = await driver.findComponent(ON.id('ArkWebPage')); + await componentButton1.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/BuilderProxyNode01.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/BuilderProxyNode01.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..19eb73e542862ddf800c95ac81067e3d284161dd --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/BuilderProxyNode01.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function BuilderProxyNode01Test() { + describe('BuilderProxyNode01Test', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','BuilderProxyNode01Test beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/BuilderProxyNode01', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get BuilderProxyNode01 state pages:' + JSON.stringify(pages)); + if (!('BuilderProxyNode01' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get BuilderProxyNode01 pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push BuilderProxyNode01 page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','BuilderProxyNode01 beforeEach end'); + }); + + it('BuilderProxyNode01Test', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: WrappedBuilderTest_01 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('BuilderProxyNode01')); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/BuilderProxyNode02.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/BuilderProxyNode02.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..896c28106806c3a2df5462d52e9dc8d517bd6682 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/BuilderProxyNode02.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function BuilderProxyNode02Test() { + describe('BuilderProxyNode02Test', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','BuilderProxyNode02Test beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/BuilderProxyNode02', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get BuilderProxyNode02 state pages:' + JSON.stringify(pages)); + if (!('BuilderProxyNode02' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get BuilderProxyNode02 pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push BuilderProxyNode02 page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','BuilderProxyNode02 beforeEach end'); + }); + + it('BuilderProxyNode02Test', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: BuilderProxyNode02Test begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('BuilderProxyNode02')); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/EnvironmentCallbackPage.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/EnvironmentCallbackPage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..2d64f5d82f2c5835de9055a4ff290b8dfe618851 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/EnvironmentCallbackPage.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function EnvironmentCallbackPageTest() { + describe('EnvironmentCallbackPageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','EnvironmentCallbackPageTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/EnvironmentCallbackPage', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get EnvironmentCallbackPage state pages:' + JSON.stringify(pages)); + if (!('EnvironmentCallbackPage' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get EnvironmentCallbackPage pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push EnvironmentCallbackPage page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','EnvironmentCallbackPage beforeEach end'); + }); + + it('EnvironmentCallbackPageTest', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: EnvironmentCallbackPageTest begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Update')); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/FrameNode.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/FrameNode.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..842919f05a4705b1179397529546deb9e140c31c --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/FrameNode.test.ets @@ -0,0 +1,51 @@ +/* + * 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 } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + +export default function FrameNodeTest() { + describe('FrameNodeTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + it('FrameNodeTest_01', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: FrameNodeTest_01 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('hello')); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/InheritFreezeOptionsPage.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/InheritFreezeOptionsPage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..d0bf0da49d6b7c2510bbff58ae9d3940c1cba2d6 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/InheritFreezeOptionsPage.test.ets @@ -0,0 +1,89 @@ +/* + * 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, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function inheritFreezeTest() { + describe('inheritFreezeTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','inheritFreezeTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/inheritFreezeOptionsPage', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get inheritFreezeOptionsPage state pages:' + JSON.stringify(pages)); + if (!('inheritFreezeOptionsPage' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get inheritFreezeOptionsPage pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push inheritFreezeOptionsPage page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','inheritFreezeOptionsPage beforeEach end'); + }); + + it('inheritFreezeTest', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: inheritFreezeTest begin'); + let driver = Driver.create(); + let componentButton1 = await driver.findComponent(ON.text('Next Page')); + await componentButton1.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + let componentButton2 = await driver.findComponent(ON.text('update builderNode')); + await componentButton2.click() + await driver.delayMs(500); + await componentButton2.click() + await driver.delayMs(500); + await componentButton2.click() + await driver.delayMs(500); + await componentButton2.click() + await driver.delayMs(500); + await componentButton2.click() + await driver.delayMs(500); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + let componentButton3 = await driver.findComponent(ON.text('Next Page')); + await componentButton3.click() + await driver.delayMs(1000); + let componentButton4 = await driver.findComponent(ON.text('Back Page')); + await componentButton4.click() + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/IsDisposedPage.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/IsDisposedPage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..365d68c9de4a07d253de98318a4b8e51cce62ff7 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/IsDisposedPage.test.ets @@ -0,0 +1,75 @@ +/* + * 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, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function isDisposedPageTest() { + describe('isDisposedPageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','isDisposedPageTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/isDisposedPage', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get isDisposedPage state pages:' + JSON.stringify(pages)); + if (!('isDisposedPage' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get isDisposedPage pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push isDisposedPage page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','isDisposedPage beforeEach end'); + }); + + it('isDisposedPageTest', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: isDisposedPageTest begin'); + let driver = Driver.create(); + let componentButton1 = await driver.findComponent(ON.text('BuilderNode isDisposed')); + await componentButton1.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + let componentButton2 = await driver.findComponent(ON.text('BuilderNode dispose')); + await componentButton2.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..e92f8614de3142752c6c2274d21373f55a144c94 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,31 @@ +import ArkWebPageTest from './ArkWebPage.test'; +import BuilderProxyNode01Test from './BuilderProxyNode01.test'; +import BuilderProxyNode02Test from './BuilderProxyNode02.test'; +import EnvironmentCallbackPageTest from './EnvironmentCallbackPage.test'; +import FrameNodeTest from './FrameNode.test'; +import inheritFreezeTest from './InheritFreezeOptionsPage.test'; +import isDisposedPageTest from './IsDisposedPage.test'; +import LocalStoragePageTest from './LocalStoragePage.test'; +import postTouchEventTest from './PostTouchEvent.test'; +import RenderNodeTest from './RenderNode.test'; +import ReusablePage01Test from './ReusablePage01.test'; +import ReusablePage02Test from './ReusablePage02.test'; +import routerPageTest from './RouterPage.test'; +import WrappedBuilderTest from './WrappedBuilder.test'; + +export default function testsuite() { + FrameNodeTest(); + RenderNodeTest(); + WrappedBuilderTest(); + postTouchEventTest(); + BuilderProxyNode01Test(); + BuilderProxyNode02Test(); + ReusablePage01Test(); + ReusablePage02Test(); + EnvironmentCallbackPageTest(); + routerPageTest(); + LocalStoragePageTest(); + isDisposedPageTest(); + inheritFreezeTest(); + ArkWebPageTest(); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/LocalStoragePage.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/LocalStoragePage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f7035723cec64da8279c32cc2253a262d698c274 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/LocalStoragePage.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function LocalStoragePageTest() { + describe('LocalStoragePageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','LocalStoragePageTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/LocalStoragePage', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get LocalStoragePage state pages:' + JSON.stringify(pages)); + if (!('LocalStoragePage' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get LocalStoragePage pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push LocalStoragePage page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','LocalStoragePage beforeEach end'); + }); + + it('LocalStoragePageTest', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: LocalStoragePageTest begin'); + let driver = Driver.create(); + let componentButton1 = await driver.findComponent(ON.id('LocalStoragePage')); + await componentButton1.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/PostTouchEvent.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/PostTouchEvent.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..c6200f6b9a807862cca770d156e7e9e5a2f97840 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/PostTouchEvent.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function postTouchEventTest() { + describe('postTouchEventTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','postTouchEventTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/postTouchEvent', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get postTouchEvent state pages:' + JSON.stringify(pages)); + if (!('postTouchEvent' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get postTouchEvent pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push postTouchEvent page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','postTouchEvent beforeEach end'); + }); + + it('postTouchEventTest_01', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: postTouchEventTest_01 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('onTouch')); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/RenderNode.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/RenderNode.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..d29e6d1d60f2d1cf6793fa724c405362de640436 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/RenderNode.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function RenderNodeTest() { + describe('RenderNodeTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','RenderNode beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/RenderNode', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get RenderNode state pages:' + JSON.stringify(pages)); + if (!('RenderNode' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get RenderNode pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push RenderNode page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','RenderNode beforeEach end'); + }); + + it('RenderNodeTest_01', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: RenderNode begin'); + let driver = Driver.create(); + let componentText = await driver.findComponent(ON.text('hello world')); + await componentText.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ReusablePage01.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ReusablePage01.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..e5bf7dfbbf5af03d6425178ec9e43cc27eca3d3b --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ReusablePage01.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function ReusablePage01Test() { + describe('ReusablePage01Test', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','ReusablePage01Test beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/ReusablePage01', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get ReusablePage01 state pages:' + JSON.stringify(pages)); + if (!('ReusablePage01' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get ReusablePage01 pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push ReusablePage01 page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','ReusablePage01 beforeEach end'); + }); + + it('ReusablePage01Test', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: ReusablePage01Test begin'); + let driver = Driver.create(); + let componentList = await driver.findComponent(ON.id('List')); + await componentList.scrollToBottom(4000); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ReusablePage02.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ReusablePage02.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..c2fb9859fffcda6bf6c00fe65b842117df39bfcb --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/ReusablePage02.test.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function ReusablePage02Test() { + describe('ReusablePage02Test', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','ReusablePage02Test beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/ReusablePage02', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get ReusablePage02 state pages:' + JSON.stringify(pages)); + if (!('ReusablePage02' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get ReusablePage02 pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push ReusablePage02 page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','ReusablePage02 beforeEach end'); + }); + + it('ReusablePage02Test', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: ReusablePage02Test begin'); + let driver = Driver.create(); + let componentList = await driver.findComponent(ON.id('ReusablePage02')); + await componentList.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/RouterPage.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/RouterPage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..526808f60bc29d23726adc0e0bd2993222dddafe --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/RouterPage.test.ets @@ -0,0 +1,75 @@ +/* + * 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, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function routerPageTest() { + describe('routerPageTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','routerPageTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/routerPage1', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get routerPage1 state pages:' + JSON.stringify(pages)); + if (!('routerPage1' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get routerPage1 pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push ReusablePage02 page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','ReusablePage02 beforeEach end'); + }); + + it('routerPageTest', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: routerPageTest begin'); + let driver = Driver.create(); + let componentButton1 = await driver.findComponent(ON.text('Router pageTwo')); + await componentButton1.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + let componentButton2 = await driver.findComponent(ON.text('Router replace to index')); + await componentButton2.click() + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/WrappedBuilder.test.ets b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/WrappedBuilder.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7aeaa4f05006ff54432b1849204fb3c26757720a --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/ets/test/WrappedBuilder.test.ets @@ -0,0 +1,74 @@ +/* + * 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, it, expect } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Router, router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + + +export default function WrappedBuilderTest() { + describe('WrappedBuilderTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(0xF811, 'testTag', '%{public}s','get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + beforeEach(() => { + hilog.info(0xF811, 'testTag', '%{public}s','WrappedBuilderTest beforeEach start'); + let options: router.RouterOptions = { + url: 'pages/WrappedBuilder', + } + try { + const routerInstance = AppStorage.get('router') as Router + let pages = routerInstance.getState(); + hilog.info(0xF811, 'testTag', '%{public}s','get WrappedBuilder state pages:' + JSON.stringify(pages)); + if (!('WrappedBuilder' == pages.name)) { + hilog.info(0xF811, 'testTag', '%{public}s','get WrappedBuilder pages.name:' + JSON.stringify(pages.name)); + routerInstance.pushUrl(options); + } + } catch (err) { + hilog.error(DOMAIN, 'testTag', '%{public}s','push WrappedBuilder page error:' + err); + } + hilog.info(0xF811, 'testTag', '%{public}s','WrappedBuilder beforeEach end'); + }); + + it('WrappedBuilderTest_01', 0, async (done: Function) => { + hilog.info(0xF811, 'testTag', '%{public}s','uitest: WrappedBuilderTest_01 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Update')); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + await componentButton.click(); + hilog.info(0xF811, 'testTag', '%{public}s','uitest: already click'); + await driver.delayMs(2000); + done(); + }) + }); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/ohosTest/module.json5 b/ArkUIKit/BuilderNode/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ca820d036b48fed99f490fd5e88f6c470ccb7868 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/ohosTest/module.json5 @@ -0,0 +1,31 @@ +/* + * 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", + "requestPermissions": [ + { + "name": "ohos.permission.INTERNET" + } + ], + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/BuilderNode/entry/src/test/List.test.ets b/ArkUIKit/BuilderNode/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/test/List.test.ets @@ -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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/entry/src/test/LocalUnit.test.ets b/ArkUIKit/BuilderNode/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/BuilderNode/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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/BuilderNode/hvigor/hvigor-config.json5 b/ArkUIKit/BuilderNode/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b8fea3f097bd68b0bc4d87de986d2cb7732c1d9b --- /dev/null +++ b/ArkUIKit/BuilderNode/hvigor/hvigor-config.json5 @@ -0,0 +1,38 @@ +/* + * 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": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | 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 */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "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/BuilderNode/hvigorfile.ts b/ArkUIKit/BuilderNode/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3340f07e45ddc5dcadbb87012668555def2e6e0 --- /dev/null +++ b/ArkUIKit/BuilderNode/hvigorfile.ts @@ -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. + */ + +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/BuilderNode/oh-package.json5 b/ArkUIKit/BuilderNode/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..69cb43cba3addcee1840403c67405134a2a9102c --- /dev/null +++ b/ArkUIKit/BuilderNode/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. + */ + +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/BuilderNode/ohosTest.md b/ArkUIKit/BuilderNode/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..8460821b3cc264c1739c6b077168917bdc5934b8 --- /dev/null +++ b/ArkUIKit/BuilderNode/ohosTest.md @@ -0,0 +1,20 @@ +# Navigation 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|-------------------------------------------------------------------------------------| -------------- |-----------------------------------------------------------------|------------------------------------------------------------------| :------- | -------- | +| 测试通过BuilderNode的build可以实现组件树的创建。 | 设备正常运行 | BuilderNode的根节点直接作为NodeController的makeNode返回值。 | 组件创建成功 | 是 | Pass | +| 测试将BuilderNode与RenderNode进行结合使用是否可以实现组件树的创建。 | 设备正常运行 | BuilderNode的RenderNode挂载节点 | 组件创建成功 | 是 | Pass | +| 测试通过BuilderNode对象的build创建组件树。 | 设备正常运行 | 使用update更新BuilderNode中的节点。 | 组件更新成功 | 是 | Pass | +| 测试通过该接口向BuilderNode中绑定的组件注入触摸事件,实现事件的模拟转发。 | 设备正常运行 | 向BuilderNode中的Column组件转发另一个Column接收的事件 | 上方的Column组件也会收到同样的触摸事件。 | 是 | Pass | +| 测试若传入的Builder的根节点为语法节点(if/else/foreach/…)或自定义组件,将额外生成一个FrameNode | 设备正常运行 | Column组件触发触摸事件 | Column的触摸测试无法传递到Row上 | 是 | Pass | +| 测试使用一个容器组件包裹语法节点或自定义组件,并将容器组件的hitTestBehavior设置为HitTestMode.Transparent,向兄弟节点传递触摸测试 | 设备正常运行 | Column组件触发触摸事件 | Column的触摸测试传递到Row上 | 是 | Pass | +| 测试调用reuse接口和recycle接口,将复用和回收事件传递至BuilderNode中的自定义组件,实现BuilderNode节点内部的自定义组件的复用 | 设备正常运行 | 调用BuilderNode的reuse和recycle接口 | 复用和回收事件传递给自定义组件ChildComponent2,达成复用效果 | 是 | Pass | +| 测试使用@Reusable装饰器时,应使用一个普通自定义组件包裹该自定义组件 | 设备正常运行 | 通过ChildComponent2对其包裹,ReusableChildComponent可以使用@Reusable装饰器标记。 | 使用@Reusable装饰器标记成功 | 是 | Pass | +| 测试使用updateConfiguration来监听系统环境变化事件,触发节点的全量更新 | 设备正常运行 | 使用updateConfiguration监听系统环境变化事件 | 节点的全量更新 | 是 | Pass | +| 测试BuilderNode在新页面被复用时,会自动刷新自身内容 | 设备正常运行 | 在页面跳转前,触发点击事件 | BuilderNode从AppStorage中移除 | 是 | Pass | +| 测试自定义组件支持接收LocalStorage实例 | 设备正常运行 | 传递LocalStorage实例 | LocalStorage相关的装饰器@LocalStorageProp、@LocalStorageLink可以使用并能接收得到值 | 是 | Pass | +| 测试使用isDisposed接口查询当前BuilderNode对象是否已解除与后端实体节点的引用关系 | 设备正常运行 | 在页面跳转前,触发点击事件 | 页面跳转,各按钮功能逻辑正常 | 是 | Pass | +| 测试当组件处于非激活状态时,即便其绑定状态变量发生变化,也不会触发组件UI的重新渲染 | 设备正常运行 | 父自定义组件的冻结策略设置为开启组件冻结 | BuilderNode节点在不活跃时将会冻结 | 是 | Pass | +| 测试结合BuilderNode,可以将ArkWeb组件提前进行离线预渲染 | 设备正常运行 | 创建NodeContainer和对应的NodeController,渲染后台Web组件 | 通过NodeContainer展示已经预渲染的页面 | 是 | Pass | \ No newline at end of file diff --git a/ArkUIKit/BuilderNode/pictures/image01.png b/ArkUIKit/BuilderNode/pictures/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..9e4a57f7ebe0ac6d1d8f49819e2728f2d397a45c Binary files /dev/null and b/ArkUIKit/BuilderNode/pictures/image01.png differ diff --git a/ArkUIKit/BuilderNode/pictures/image02.png b/ArkUIKit/BuilderNode/pictures/image02.png new file mode 100644 index 0000000000000000000000000000000000000000..60e079bde21435d5b5d722256ce3f9a22bfa42e1 Binary files /dev/null and b/ArkUIKit/BuilderNode/pictures/image02.png differ diff --git a/ArkUIKit/BuilderNode/pictures/image03.png b/ArkUIKit/BuilderNode/pictures/image03.png new file mode 100644 index 0000000000000000000000000000000000000000..67847bb584bb002ae72a0a94b0de19fd9c4e60db Binary files /dev/null and b/ArkUIKit/BuilderNode/pictures/image03.png differ diff --git a/ArkUIKit/ButtonAttribute/AppScope/app.json5 b/ArkUIKit/ButtonAttribute/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f4cafaa77f984b66d51d3fc167f35b5f122a3aa0 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/AppScope/app.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. + */ + +{ + "app": { + "bundleName": "com.samples.ButtonAttribute", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/ButtonAttribute/AppScope/resources/base/element/string.json b/ArkUIKit/ButtonAttribute/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/background.png b/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/foreground.png b/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/layered_image.json b/ArkUIKit/ButtonAttribute/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/README_zh.md b/ArkUIKit/ButtonAttribute/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..7add20ca071b05334c9bcace656e66d6934be35b --- /dev/null +++ b/ArkUIKit/ButtonAttribute/README_zh.md @@ -0,0 +1,99 @@ +# 属性修改器 (AttributeModifier)指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [属性修改器 (AttributeModifier)](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/arkts-user-defined-extension-attributeModifier.md)。 + +### 效果预览 + +| 按钮1 | 按钮2 | 按钮3 | 按钮4 | +|---------------------------|---------------------------|---------------------------|-------------------------------------| +| ![](pictures/image01.png) | ![](pictures/image02.png) | ![](pictures/image03.png) | ![](pictures/image04.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---Common +| |---ButtonModifier01.ets //定义ButtonModifier +| |---ButtonModifier02.ets //定义ButtonModifier +| |---ButtonModifier03.ets //定义ButtonModifier +| |---ButtonModifier04.ets //定义ButtonModifier +|---entryability +|---pages +| |---AttributeDemo01.ets // 按钮主题切换与多态样式 +entry/src/ohosTest/ +|---ets +| |---Attribute.test.ets // 对应页面测试代码 +``` +### 具体实现 +一、使用AttributeModifier实现按钮主题切换与多态样式: +1. 定义ButtonThemeModifier类,实现AttributeModifier接口,声明isDarkTheme成员变量(控制主题),通过构造函数初始化默认主题; +2. 实现applyNormalAttribute方法:根据isDarkTheme值,分别设置深色主题(#333333背景、#FFFFFF字体)和浅色主题(#FFFFFF背景、#333333字体),同时配置圆角、内边距; +3. 实现applyPressedAttribute方法:覆盖正常态样式,深色主题按压时设#111111背景,浅色主题按压时设#F5F5F5背景,优化交互反馈。 + +二、在页面中调用该接口: +1. 在ThemeButtonDemo.ets中,用@State修饰ButtonThemeModifier实例(初始浅色主题); +2. Button组件通过.attributeModifier(this.themeModifier)绑定样式; +3. 点击Button时,修改this.themeModifier.isDarkTheme的值,触发UI刷新切换主题; +4. 文本组件显示当前主题状态,辅助用户感知切换效果。 + +三、使用AttributeModifier实现文本按内容长度动态调整样式: +1. 定义AdaptiveTextModifier类,实现AttributeModifier接口,声明content(文本内容)和baseFontSize(基础字体大小)成员变量,构造函数传入初始值; +2. 在applyNormalAttribute方法中,通过this.content.length判断文本长度: + (1)长度>20:设字体大小baseFontSize-4、#FF4444颜色、maxWidth=200,添加文本溢出省略; + (2)长度10~20:设默认字体大小、#FF9900颜色、maxWidth=150; + (3)长度≤10:设字体大小baseFontSize+2、#00C853颜色、加粗样式。 + +五、使用AttributeModifier实现输入框多状态样式控制: +1. 定义InputStateModifier类,实现AttributeModifier接口,声明isDisabled(禁用状态)和hasError(错误状态)成员变量; +2. 实现applyNormalAttribute方法: + (1)若isDisabled为true:设#F5F5F5背景、#DDDDDD边框、#AAAAAA字体,标记禁用态; + (2)若hasError为true:设#FF4444边框(宽度2)、#FF4444字体,标记错误态; + (3)正常状态:设#CCCCCC边框(宽度1)、#333333字体,基础样式配置宽高和内边距; +3. 实现applyFocusedAttribute方法:非禁用状态下,设#2196F3边框(宽度2)、#F0F7FF背景,突出聚焦态。 + +六、使用AttributeModifier实现列表项多态交互样式: +1. 定义ListItemInteractionModifier类,实现AttributeModifier接口,声明isSelected(选中状态)成员变量; +2. 实现applyNormalAttribute方法:根据isSelected值,设选中态#E3F2FD背景、未选中态#FFFFFF背景,统一配置宽高和内边距; +3. 实现applySelectedAttribute方法:覆盖正常态,设#BBDEFB背景、左侧4px宽#2196F3边框,明确选中标识; +4. 实现applyPressedAttribute方法:覆盖选中/正常态,设#90CAF9背景,增强按压反馈。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行, 支持设备:Mate 70 Pro。 + +2.本示例为Stage模型,支持API18版本full-SDK,版本号:5.1.0.107,镜像版本号:OpenHarmony_5.1.0 Release。 + +3.本示例需要使用DevEco Studio 5.0.5 Release (Build Version: 5.0.13.200, built on May 13, 2025)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/ButtonAttribute > .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/ButtonAttribute/build-profile.json5 b/ArkUIKit/ButtonAttribute/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4bf5632ff8eaccffcf9a2a7dec209e36ddc3a371 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/build-profile.json5 @@ -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. + */ + +{ + "app": { + "signingConfigs": [ + + ], + "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" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/code-linter.json5 b/ArkUIKit/ButtonAttribute/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ed05653cca31b61d64cf6471529eaf50d4f70709 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/code-linter.json5 @@ -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. + */ + +{ + "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/ButtonAttribute/entry/build-profile.json5 b/ArkUIKit/ButtonAttribute/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6bf0d132e6f78049e712446c63f2633b2d1613d3 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/build-profile.json5 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/hvigorfile.ts b/ArkUIKit/ButtonAttribute/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/hvigorfile.ts @@ -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. + */ + +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/ButtonAttribute/entry/obfuscation-rules.txt b/ArkUIKit/ButtonAttribute/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/entry/oh-package.json5 b/ArkUIKit/ButtonAttribute/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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": {} +} + diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier01.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier01.ets new file mode 100644 index 0000000000000000000000000000000000000000..94fc3d8e2c315209250ddb027d3c2ef536ff3c0c --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier01.ets @@ -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 Common_AttributeModifier] +declare interface AttributeModifier { + + applyNormalAttribute?(instance: T): void; + + applyPressedAttribute?(instance: T): void; + + applyFocusedAttribute?(instance: T): void; + + applyDisabledAttribute?(instance: T): void; + + applySelectedAttribute?(instance: T): void; + +} +// [End Common_AttributeModifier] + +// [Start Common_CommonMethod] +declare class CommonMethod { + attributeModifier(modifier: AttributeModifier): T; +} +// [End Common_CommonMethod] + +// [Start Common_MyButtonModifier] +export class MyButtonModifier implements AttributeModifier { + public isDark: boolean = false + + constructor(dark?: boolean) { + this.isDark = dark ?? false + } + + applyNormalAttribute(instance: ButtonAttribute): void { + if (this.isDark) { + instance.backgroundColor('#707070') + } else { + instance.backgroundColor('#17A98D') + .borderColor('#707070') + .borderWidth(2) + } + } +} +// [End Common_MyButtonModifier] diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier02.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier02.ets new file mode 100644 index 0000000000000000000000000000000000000000..4de4d6c0e7771cad6e7db08df1c7bc64103ba2a3 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier02.ets @@ -0,0 +1,51 @@ +/* + * 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. + */ + +declare interface AttributeModifier { + + applyNormalAttribute?(instance: T): void; + + applyPressedAttribute?(instance: T): void; + + applyFocusedAttribute?(instance: T): void; + + applyDisabledAttribute?(instance: T): void; + + applySelectedAttribute?(instance: T): void; + +} + +declare class CommonMethod { + attributeModifier(modifier: AttributeModifier): T; +} +// [Start Common_MyButtonModifier2] +export class MyButtonModifier2 implements AttributeModifier { + public isDark: boolean = false + + constructor(dark?: boolean) { + this.isDark = dark ?? false + } + + applyNormalAttribute(instance: ButtonAttribute): void { + if (this.isDark) { + instance.backgroundColor(Color.Black) + .width(200) + } else { + instance.backgroundColor(Color.Red) + .width(100) + } + } +} + // [End Common_MyButtonModifier2] \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier03.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier03.ets new file mode 100644 index 0000000000000000000000000000000000000000..ced8f89d105faaf81a63f93b0e06d66c9307c9c7 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier03.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. + */ + +declare interface AttributeModifier { + + applyNormalAttribute?(instance: T): void; + + applyPressedAttribute?(instance: T): void; + + applyFocusedAttribute?(instance: T): void; + + applyDisabledAttribute?(instance: T): void; + + applySelectedAttribute?(instance: T): void; + +} + +declare class CommonMethod { + attributeModifier(modifier: AttributeModifier): T; +} +// [Start Common_MyButtonModifier3] +export class MyButtonModifier3 implements AttributeModifier { + public isDark2: boolean = false + + constructor(dark?: boolean) { + this.isDark2 = dark ? dark : false + } + + applyNormalAttribute(instance: ButtonAttribute): void { + if (this.isDark2) { + instance.backgroundColor('#2787D9') + } else { + instance.backgroundColor('#707070') + } + } +} + // [End Common_MyButtonModifier3] \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier04.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier04.ets new file mode 100644 index 0000000000000000000000000000000000000000..950e24554523db9c641d55b012c1cbedc4b54a5c --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/Common/ButtonModifier04.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. + */ + +declare interface AttributeModifier { + + applyNormalAttribute?(instance: T): void; + + applyPressedAttribute?(instance: T): void; + + applyFocusedAttribute?(instance: T): void; + + applyDisabledAttribute?(instance: T): void; + + applySelectedAttribute?(instance: T): void; + +} + +declare class CommonMethod { + attributeModifier(modifier: AttributeModifier): T; +} +// [Start Common_MyButtonModifier4] +export class MyButtonModifier4 implements AttributeModifier { + applyNormalAttribute(instance: ButtonAttribute): void { + instance.backgroundColor('#17A98D') + .borderColor('#707070') + .borderWidth(2) + } + + applyPressedAttribute(instance: ButtonAttribute): void { + instance.backgroundColor('#2787D9') + .borderColor('#FFC000') + .borderWidth(5) + } +} +// [End Common_MyButtonModifier4] \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0526afd677c7f7a7250fa470c0b5fa7ebf6146c6 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/entryability/EntryAbility.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. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/attributeDemo_01', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * 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/ButtonAttribute/entry/src/main/ets/pages/AttributeDemo01.ets b/ArkUIKit/ButtonAttribute/entry/src/main/ets/pages/AttributeDemo01.ets new file mode 100644 index 0000000000000000000000000000000000000000..47fb4b8ba4f758e64920b97ba9b7e56b95c17a88 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/ets/pages/AttributeDemo01.ets @@ -0,0 +1,73 @@ +/* + * 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 { MyButtonModifier } from '../Common/ButtonModifier01'; +import { MyButtonModifier2 } from '../Common/ButtonModifier02'; +import { MyButtonModifier3 } from '../Common/ButtonModifier03'; +import { MyButtonModifier4 } from '../Common/ButtonModifier04' + +@Entry +@Component +struct attributeDemo_01 { + @State modifier: MyButtonModifier = new MyButtonModifier(true); + @State modifier2: MyButtonModifier = new MyButtonModifier(true); + @State modifier3: MyButtonModifier2 = new MyButtonModifier2(true); + @State modifier4: MyButtonModifier3 = new MyButtonModifier3(true); + @State modifier5: MyButtonModifier4 = new MyButtonModifier4(); + + build() { + Row() { + Column({space:20}) { + // [Start main_button1] + Button('Button1') + .id('btn') + .attributeModifier(this.modifier) + .onClick(() => { + this.modifier.isDark = !this.modifier.isDark + }) + // [End main_button1] + + // [Start main_button2] + Button('Button2') + .id('btn2') + .backgroundColor('#2787D9') + .attributeModifier(this.modifier2) + .onClick(() => { + this.modifier2.isDark = !this.modifier2.isDark + }) + // [End main_button2] + + // [Start main_button3] + Button('Button3') + .id('btn3') + .attributeModifier(this.modifier3) + .attributeModifier(this.modifier4) + .onClick(() => { + this.modifier3.isDark = !this.modifier3.isDark + this.modifier4.isDark2 = !this.modifier4.isDark2 + }) + // [End main_button3] + + // [Start main_button4] + Button('Button4') + .id('btn4') + .attributeModifier(this.modifier5) + // [End main_button4] + } + .width('100%') + } + .height('100%') + } +} diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/module.json5 b/ArkUIKit/ButtonAttribute/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..22931d03cb276dbf2b7158dbb20de048c8ec8400 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/module.json5 @@ -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. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "phone" + ], + "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": [ + "ohos.want.action.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/ButtonAttribute/entry/src/main/resources/base/element/color.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/entry/src/main/resources/base/element/float.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/entry/src/main/resources/base/element/string.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/background.png b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..5b2b03c6698ac8656b11d2610faab4fe7a2762ce --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/AttributeDemo01" + ] +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/main/resources/dark/element/color.json b/ArkUIKit/ButtonAttribute/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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/ButtonAttribute/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/ButtonAttribute/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..02775375b03271d39235883ad6b8eba1563ee477 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/ohosTest/ets/test/List.test.ets @@ -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 attributeTest from './attribute.test'; + +export default function testsuite() { + attributeTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/ohosTest/ets/test/attribute.test.ets b/ArkUIKit/ButtonAttribute/entry/src/ohosTest/ets/test/attribute.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..67fca0f9d50cc1cb923f254c8ad01a654139c945 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/ohosTest/ets/test/attribute.test.ets @@ -0,0 +1,101 @@ +/* + * 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 } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; + +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 attributeTest() { + describe('attributeTest', () => { + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info('get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + /** + * @tc.number UiTest_041 + * @tc.name testArcListArcIndexerBar + * @tc.desc 测试弧形列表联动indexer示例 + */ + + it('attributeTest_01', 0, async (done: Function) => { + console.info('uitest: attributeTest_01 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('btn')); + await componentButton.click(); + console.info('uitest: already click'); + await driver.delayMs(2000); + await componentButton.click(); + console.info('uitest: click end'); + await driver.delayMs(1000); + done(); + }) + + it('attributeTest_02', 0, async (done: Function) => { + console.info('uitest: attributeTest_02 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('btn2')); + await componentButton.click(); + console.info('uitest: already click'); + await driver.delayMs(2000); + await componentButton.click(); + console.info('uitest: click end'); + await driver.delayMs(1000); + done(); + }) + + it('attributeTest_03', 0, async (done: Function) => { + console.info('uitest: attributeTest_03 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('btn3')); + await componentButton.click(); + console.info('uitest: already click'); + await driver.delayMs(2000); + await componentButton.click(); + console.info('uitest: click end'); + await driver.delayMs(1000); + done(); + }) + + it('attributeTest_04', 0, async (done: Function) => { + console.info('uitest: attributeTest_04 begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('btn4')); + await componentButton.longClick(); + console.info('uitest: already longClick'); + await driver.delayMs(2000); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/ohosTest/module.json5 b/ArkUIKit/ButtonAttribute/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d73870d7e8107a2db80744bd1c2d4dac81b81388 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * 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", + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/ButtonAttribute/entry/src/test/List.test.ets b/ArkUIKit/ButtonAttribute/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/test/List.test.ets @@ -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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ButtonAttribute/entry/src/test/LocalUnit.test.ets b/ArkUIKit/ButtonAttribute/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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/ButtonAttribute/hvigor/hvigor-config.json5 b/ArkUIKit/ButtonAttribute/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b8fea3f097bd68b0bc4d87de986d2cb7732c1d9b --- /dev/null +++ b/ArkUIKit/ButtonAttribute/hvigor/hvigor-config.json5 @@ -0,0 +1,38 @@ +/* + * 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": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | 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 */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "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/ButtonAttribute/hvigorfile.ts b/ArkUIKit/ButtonAttribute/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3340f07e45ddc5dcadbb87012668555def2e6e0 --- /dev/null +++ b/ArkUIKit/ButtonAttribute/hvigorfile.ts @@ -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. + */ + +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/ButtonAttribute/oh-package.json5 b/ArkUIKit/ButtonAttribute/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..69cb43cba3addcee1840403c67405134a2a9102c --- /dev/null +++ b/ArkUIKit/ButtonAttribute/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. + */ + +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/ButtonAttribute/ohosTest.md b/ArkUIKit/ButtonAttribute/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..76bf5976c2a47118f3b54eac3fc81ff32c22fc4e --- /dev/null +++ b/ArkUIKit/ButtonAttribute/ohosTest.md @@ -0,0 +1,10 @@ +# 属性修改器 (AttributeModifier) 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ------------------- | -------------- |----------------------------------------------------|-------------| :------- | -------- | +| 测试AttributeModifier可以分离UI与样式,支持参数传递及业务逻辑编写,并且通过状态变量触发刷新。 | 设备正常运行 | 通过点击按钮让对象的一层属性被修改,会触发UI刷新,重新执行applyNormalAttribute | 按钮颜色改变 | 是 | Pass | +| 测试当一个组件上同时使用属性方法和applyNormalAttribute设置相同的属性时,遵循属性覆盖原则,即后设置的属性生效。 | 设备正常运行 | 按钮颜色会跟随modifier的值改变 | 按钮颜色改变 | 是 | Pass | +| 测试当一个组件上多次使用applyNormalAttribute设置不同的Modifier实例时,每次状态变量刷新均会按顺序执行这些实例的方法属性设置 | 设备正常运行 | 按钮颜色会跟随modifier的值改变 | 按钮颜色改变 | 是 | Pass | +| 测试在组件进入按压态时设置某些属性,通过自定义实现applyPressedAttribute方法完成 | 设备正常运行 | 长按按钮,按钮从正常状态的颜色变为按压状态的颜色 | 按钮颜色改变 | 是 | Pass | diff --git a/ArkUIKit/ButtonAttribute/pictures/attributeModifier.png b/ArkUIKit/ButtonAttribute/pictures/attributeModifier.png new file mode 100644 index 0000000000000000000000000000000000000000..869f8e8056501f465623311d1ddc35c32d0baa3c Binary files /dev/null and b/ArkUIKit/ButtonAttribute/pictures/attributeModifier.png differ diff --git a/ArkUIKit/ButtonAttribute/pictures/image01.png b/ArkUIKit/ButtonAttribute/pictures/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..7d13a9b548da8b7c2406be0a35e2f5202a788b72 Binary files /dev/null and b/ArkUIKit/ButtonAttribute/pictures/image01.png differ diff --git a/ArkUIKit/ButtonAttribute/pictures/image02.png b/ArkUIKit/ButtonAttribute/pictures/image02.png new file mode 100644 index 0000000000000000000000000000000000000000..77175b68b306939aa44d6d417615c5c54a1aea63 Binary files /dev/null and b/ArkUIKit/ButtonAttribute/pictures/image02.png differ diff --git a/ArkUIKit/ButtonAttribute/pictures/image03.png b/ArkUIKit/ButtonAttribute/pictures/image03.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1e378531dd7b4dca426da3e1cd6af1e35f1331 Binary files /dev/null and b/ArkUIKit/ButtonAttribute/pictures/image03.png differ diff --git a/ArkUIKit/ButtonAttribute/pictures/image04.png b/ArkUIKit/ButtonAttribute/pictures/image04.png new file mode 100644 index 0000000000000000000000000000000000000000..e56a14befd9427554d5f9ccf7470f611c2ad710d Binary files /dev/null and b/ArkUIKit/ButtonAttribute/pictures/image04.png differ diff --git a/ArkUIKit/ButtonList/AppScope/app.json5 b/ArkUIKit/ButtonList/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..2b8dc77c345c9f82b7dedc86665b3b69bc25c86d --- /dev/null +++ b/ArkUIKit/ButtonList/AppScope/app.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. + */ + +{ + "app": { + "bundleName": "com.samples.ButtonList", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/ButtonList/AppScope/resources/base/element/string.json b/ArkUIKit/ButtonList/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/ArkUIKit/ButtonList/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/ArkUIKit/ButtonList/AppScope/resources/base/media/background.png b/ArkUIKit/ButtonList/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ButtonList/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/ButtonList/AppScope/resources/base/media/foreground.png b/ArkUIKit/ButtonList/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/ButtonList/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ButtonList/AppScope/resources/base/media/layered_image.json b/ArkUIKit/ButtonList/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/README_zh.md b/ArkUIKit/ButtonList/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..fc3b90b2e26828d7242a4e6605056f1b424c7717 --- /dev/null +++ b/ArkUIKit/ButtonList/README_zh.md @@ -0,0 +1,96 @@ +# 接入ArkTS页面指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI开发文档](https://gitcode.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1.[接入ArkTS页面](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/ndk-access-the-arkts-page)。 + +### 效果预览 + +| 首页 | +|---------------------------| +| ![](pictures/image01.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/cpp/ +|---types +| |---index.d.ts //应用启动页,加载承载Native的容器。。 +|---ArkUIBaseNode.h //节点封装扩展类。 +|---ArkUIListItemNode.h //节点封装扩展类。 +|---ArkUIListNode.h //节点封装扩展类。 +|---ArkUINode.h //节点封装扩展类。 +|---ArkUITextNode.h //节点封装扩展类。 +|---CMakeLists.txt //C语言库引用文件。 +|---napi_init.cpp //与index.d.ts对应的桥接方法对接Native侧的定义处。 +|---NativeEntry.cpp //桥接方法的Native侧实现。 +|---NativeEntry.h //桥接方法的Native侧定义。 +|---NativeModule.h +|---NormalTextListExample.h //示例代码文件。 + +entry/src/main/ets/ +|---entryability +|---entrybackupability +|---pages +| |---index.ets //应用启动页,加载承载Native的容器。 +entry/src/ohosTest/ +|---ets +| |---index.test.ets // 对应页面测试代码 +``` + +### 具体实现 + +一、ArkTS侧占位组件配置与Native交互触发 +1. 初始化占位组件依赖:创建NodeContent对象(rootSlot),作为Native组件挂载的桥梁; +2. 状态控制显示逻辑:用@State @Watch('changeNativeFlag')修饰showNative变量,变量变化时触发回调; +3. 绑定占位组件:通过ContentSlot(rootSlot)在UI中声明占位区域,与NodeContent绑定; +4. 交互触发Native操作:changeNativeFlag回调中,根据showNative值调用Native接口(createNativeRoot/destroyNativeRoot),传递NodeContent用于挂载/卸载Native组件。 + +二、Native侧UI组件封装(基类+列表/文本组件) +1. 基类封装通用能力:ArkUIBaseNode封装节点生命周期(析构时移除子节点、释放资源)和树操作(AddChild/RemoveChild);ArkUINode继承基类,封装通用属性设置(SetWidth/SetBackgroundColor等); +2. 具体组件封装:ArkUIListNode创建ARKUI_NODE_LIST类型节点,封装滚动条状态设置(SetScrollBarState);ArkUITextNode创建ARKUI_NODE_TEXT类型节点,封装字体大小、颜色、文本内容等属性设置; + +三、Native侧文本列表组件创建与挂载 +1. 列表组件初始化:创建ArkUIListNode实例,设置宽高占比(SetPercentWidth(1)/SetPercentHeight(1))和滚动条显示(SetScrollBarState(true)); +2. 列表项批量创建:循环生成30个ListItem,每个ListItem中创建TextNode,设置文本内容(std::to_string(i))、字体大小(16)、颜色(0xFFff00ff)、背景色(0xFFfffacd)等属性; +3. 组件树组装:将TextNode插入ListItem,再将ListItem添加到List,形成完整列表树; +4. 挂载到ArkTS:返回List组件实例,通过NativeEntry::SetRootNode将其添加到NodeContent,完成Native组件挂载。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行, 支持设备:Mate70Pro、RK3568。 + +2.本示例为Stage模型,支持API20版本full-SDK,版本号:5.1.0.107,镜像版本号:OpenHarmony_5.1.0 Release。 + +3.本示例需要使用DevEco Studio 5.0.5 Release (Build Version: 5.0.13.200, built on May 13, 2025)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/ButtonList > .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/ButtonList/build-profile.json5 b/ArkUIKit/ButtonList/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9cc015ac83d13f6ee1fa015ac55770fd06e1dba5 --- /dev/null +++ b/ArkUIKit/ButtonList/build-profile.json5 @@ -0,0 +1,63 @@ +/* + * 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": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": [ + "arm64-v8a", + "x86_64" + ] + } + }, + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/code-linter.json5 b/ArkUIKit/ButtonList/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ed05653cca31b61d64cf6471529eaf50d4f70709 --- /dev/null +++ b/ArkUIKit/ButtonList/code-linter.json5 @@ -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. + */ + +{ + "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/ButtonList/entry/build-profile.json5 b/ArkUIKit/ButtonList/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3974c0bbe91b785fb2f765d1e8ba3cb31e2ae74c --- /dev/null +++ b/ArkUIKit/ButtonList/entry/build-profile.json5 @@ -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. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + }, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + } + }, + "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/ButtonList/entry/hvigorfile.ts b/ArkUIKit/ButtonList/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/hvigorfile.ts @@ -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. + */ + +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/ButtonList/entry/obfuscation-rules.txt b/ArkUIKit/ButtonList/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/entry/oh-package.json5 b/ArkUIKit/ButtonList/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..118bdd4fe7699368a010e04c24f5bfc887cf1298 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/oh-package.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. + */ + +{ + "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/ButtonList/entry/src/main/cpp/ArkUIBaseNode.h b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIBaseNode.h new file mode 100644 index 0000000000000000000000000000000000000000..88045426a7c9c8834ba0785e1564ab9b7796adae --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIBaseNode.h @@ -0,0 +1,83 @@ +/* + * 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 Cpp_ArkUIBaseNode] +#ifndef MYAPPLICATION_ARKUIBASENODE_H +#define MYAPPLICATION_ARKUIBASENODE_H + +#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); + } + } + + 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 OnInsertChild(const std::shared_ptr &child, int32_t index) {} + + ArkUI_NodeHandle handle_; + ArkUI_NativeNodeAPI_1 *nativeModule_ = nullptr; + +private: + std::list> children_; +}; +} + +#endif +// [End Cpp_ArkUIBaseNode] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIListItemNode.h b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIListItemNode.h new file mode 100644 index 0000000000000000000000000000000000000000..e2ec45107fa6ec62c206217991d865aba7d0b15f --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIListItemNode.h @@ -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. + */ +// [Start Cpp_ArkUIListItemNode] +#ifndef MYAPPLICATION_ARKUISTACKNODE_H +#define MYAPPLICATION_ARKUISTACKNODE_H + +#include "ArkUINode.h" + +namespace NativeModule { +class ArkUIListItemNode : public ArkUINode { +public: + ArkUIListItemNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM)) {} +}; +} + +#endif +// [End Cpp_ArkUIListItemNode] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIListNode.h b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIListNode.h new file mode 100644 index 0000000000000000000000000000000000000000..5b1ba76997da345096255970792946cb7a31a69f --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUIListNode.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. + */ +// [Start Cpp_ArkUIListNode] +#ifndef MYAPPLICATION_ARKUILISTNODE_H +#define MYAPPLICATION_ARKUILISTNODE_H + +#include "ArkUINode.h" + +namespace NativeModule { +class ArkUIListNode : public ArkUINode { +public: + ArkUIListNode() + : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {} + + ~ArkUIListNode() override {} + 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); + } +}; +} + +#endif +// [End Cpp_ArkUIListNode] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUINode.h b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUINode.h new file mode 100644 index 0000000000000000000000000000000000000000..8a0f8e03c1f0cf238dba0c8d3d28cabe41cbb0cc --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUINode.h @@ -0,0 +1,80 @@ +/* + * 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 Cpp_ArkUINode] +#ifndef MYAPPLICATION_ARKUINODE_H +#define MYAPPLICATION_ARKUINODE_H + +#include "ArkUIBaseNode.h" +#include "NativeModule.h" +#include +#include + +namespace NativeModule { + +class ArkUINode : public ArkUIBaseNode { +public: + explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) {} + + ~ArkUINode() override {} + + void SetWidth(float width) + { + ArkUI_NumberValue value[] = {{.f32 = width}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_WIDTH, &item); + } + void SetPercentWidth(float percent) + { + ArkUI_NumberValue value[] = {{.f32 = percent}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item); + } + void SetHeight(float height) + { + ArkUI_NumberValue value[] = {{.f32 = height}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item); + } + void SetPercentHeight(float percent) + { + ArkUI_NumberValue value[] = {{.f32 = percent}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item); + } + void SetBackgroundColor(uint32_t color) + { + ArkUI_NumberValue value[] = {{.u32 = color}}; + ArkUI_AttributeItem item = {value, 1}; + nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item); + } + +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 OnInsertChild(const std::shared_ptr &child, int32_t index) override + { + nativeModule_->insertChildAt(handle_, child->GetHandle(), index); + } +}; +} + +#endif +// [End Cpp_ArkUINode] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUITextNode.h b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUITextNode.h new file mode 100644 index 0000000000000000000000000000000000000000..9ab4beca4175345c7588057553b513863ce4ba57 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/ArkUITextNode.h @@ -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. + */ +// ArkUITextNode.h +// 实现文本组件的封装类。 +// [Start Cpp_ArkUITextNode] +#ifndef MYAPPLICATION_ARKUITEXTNODE_H +#define MYAPPLICATION_ARKUITEXTNODE_H + +#include "ArkUINode.h" + +#include + +namespace NativeModule { +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); + } +}; +} + +#endif +// [End Cpp_ArkUITextNode] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/CMakeLists.txt b/ArkUIKit/ButtonList/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..12910c53e4cedbbe42168d647219f4731387145d --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +# the minimum version of CMake. + +cmake_minimum_required(VERSION 3.5.0) +project(product_1) + +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) + +target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so) \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/NativeEntry.cpp b/ArkUIKit/ButtonList/entry/src/main/cpp/NativeEntry.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a034f66fd907fe3989161a69e6ec34978626ec6d --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/NativeEntry.cpp @@ -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. + */ +// NativeEntry.cpp +// [Start Cpp_NativeEntry] +#include +#include +#include +#include "NativeEntry.h" +#include "NormalTextListExample.h" + +namespace NativeModule { + +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 Cpp_NativeEntry] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/NativeEntry.h b/ArkUIKit/ButtonList/entry/src/main/cpp/NativeEntry.h new file mode 100644 index 0000000000000000000000000000000000000000..9118d85cabcb8a2cd6f77bdc2271f2b533c867c3 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/NativeEntry.h @@ -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. + */ +// [Start Cpp_Native] +#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 DestroyNativeRoot(napi_env env, napi_callback_info info); + +class NativeEntry { +public: + static NativeEntry *GetInstance() + { + static NativeEntry nativeEntry; + return &nativeEntry; + } + + void SetContentHandle(ArkUI_NodeContentHandle handle) + { + handle_ = handle; + } + + void SetRootNode(const std::shared_ptr &baseNode) + { + root_ = baseNode; + OH_ArkUI_NodeContent_AddNode(handle_, root_->GetHandle()); + } + void DisposeRootNode() + { + OH_ArkUI_NodeContent_RemoveNode(handle_, root_->GetHandle()); + root_.reset(); + } + +private: + std::shared_ptr root_; + ArkUI_NodeContentHandle handle_; +}; + +} + +#endif +// [End Cpp_Native] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/NativeModule.h b/ArkUIKit/ButtonList/entry/src/main/cpp/NativeModule.h new file mode 100644 index 0000000000000000000000000000000000000000..1162f08096351ec70d93ccdef68c88c8317337bf --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/NativeModule.h @@ -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. + */ +// [Start Cpp_NativeModule] +#ifndef MYAPPLICATION_NATIVEMODULE_H +#define MYAPPLICATION_NATIVEMODULE_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_); + } + ArkUI_NativeNodeAPI_1 *GetNativeNodeAPI() { return arkUINativeNodeApi_; } + +private: + ArkUI_NativeNodeAPI_1 *arkUINativeNodeApi_ = nullptr; +}; + +} + +#endif +// [End Cpp_NativeModule] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/NormalTextListExample.h b/ArkUIKit/ButtonList/entry/src/main/cpp/NormalTextListExample.h new file mode 100644 index 0000000000000000000000000000000000000000..b47e9e9e14235de97c48dbe7ad218815920301b8 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/NormalTextListExample.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 Cpp_NormalTextListExample] +#ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H +#define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H + +#include "ArkUIBaseNode.h" +#include "ArkUIListItemNode.h" +#include "ArkUIListNode.h" +#include "ArkUITextNode.h" +#include + +namespace NativeModule { + +std::shared_ptr CreateTextListExample() +{ + auto list = std::make_shared(); + list->SetPercentWidth(1); + list->SetPercentHeight(1); + list->SetScrollBarState(true); + const int itemCount = 30; + const int fontSizes = 16; + const int screenWidth = 300; + const int defaultHeight = 100; + for (int32_t i = 0; i < itemCount; ++i) { + auto listItem = std::make_shared(); + auto textNode = std::make_shared(); + textNode->SetTextContent(std::to_string(i)); + textNode->SetFontSize(fontSizes); + textNode->SetFontColor(0xFFff00ff); + textNode->SetPercentWidth(1); + textNode->SetWidth(screenWidth); + textNode->SetHeight(defaultHeight); + textNode->SetBackgroundColor(0xFFfffacd); + textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); + listItem->InsertChild(textNode, i); + list->AddChild(listItem); + } + return list; +} +} + +#endif +// [End Cpp_NormalTextListExample] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/ButtonList/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09af7fd2a734b18f8b0b41da30a4ce2a9b92d593 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/napi_init.cpp @@ -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. + */ +// [Start napi_init] +#include "napi/native_api.h" +#include "NativeEntry.h" + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + // 绑定Native侧的创建组件和销毁组件。 + napi_property_descriptor desc[] = { + {"createNativeRoot", nullptr, + NativeModule::CreateNativeRoot, nullptr, nullptr, + nullptr, napi_default, nullptr}, + {"destroyNativeRoot", nullptr, + NativeModule::DestroyNativeRoot, 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); } +// [End napi_init] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/types/libentry/Index.d.ts b/ArkUIKit/ButtonList/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..a04fbafcc7e80014a78a76db2097bc8c97b7d7b9 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,18 @@ +/* + * 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 Cpp_indexes] +export const createNativeRoot: (content: Object) => void; +export const destroyNativeRoot: () => void; +// [End Cpp_indexes] \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/cpp/types/libentry/oh-package.json5 b/ArkUIKit/ButtonList/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6abf3b7c20f22c62aaac6a995a25cae672f73f35 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -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. + */ + +{ + "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/ButtonList/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/ButtonList/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..42223f2933e71c0dea0306c75b3f117f5185514d --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/ets/entryability/EntryAbility.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. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/ButtonList/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * 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/ButtonList/entry/src/main/ets/pages/Index.ets b/ArkUIKit/ButtonList/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..bcd4f67e646ba885407a24629d74c74c94fce7c6 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/ets/pages/Index.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. + */ + +// [Start Main_Index] +import nativeNode from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private rootSlot:NodeContent = new NodeContent(); + @State @Watch('changeNativeFlag') showNative: boolean = false; + + changeNativeFlag(): void { + if (this.showNative) { + nativeNode.createNativeRoot(this.rootSlot) + } else { + nativeNode.destroyNativeRoot() + } + } + + build() { + Column() { + Button(this.showNative ? 'HideNativeUI' : 'ShowNativeUI') + .onClick(() => { + this.showNative = !this.showNative + }) + .id('btn') + Row() { + ContentSlot(this.rootSlot) + }.layoutWeight(1) + } + .width('100%') + .height('100%') + } +} +// [End Main_Index] diff --git a/ArkUIKit/ButtonList/entry/src/main/module.json5 b/ArkUIKit/ButtonList/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a4ed39b261e99d9d7294de007196f6d85bd2a988 --- /dev/null +++ b/ArkUIKit/ButtonList/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": [ + "ohos.want.action.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/ButtonList/entry/src/main/resources/base/element/color.json b/ArkUIKit/ButtonList/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/entry/src/main/resources/base/element/float.json b/ArkUIKit/ButtonList/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/ArkUIKit/ButtonList/entry/src/main/resources/base/element/string.json b/ArkUIKit/ButtonList/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/main/resources/base/media/background.png b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/ButtonList/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ButtonList/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/ButtonList/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/ButtonList/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/ButtonList/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/ButtonList/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ArkUIKit/ButtonList/entry/src/main/resources/dark/element/color.json b/ArkUIKit/ButtonList/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/entry/src/main/syscap.json b/ArkUIKit/ButtonList/entry/src/main/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..17ee23b5f7d4c4d9a0dba36a2cf2f5184940b62b --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/main/syscap.json @@ -0,0 +1,15 @@ +{ + "devices": { + "general": ["default","tablet"], + "custom": [ + { + "xts": [ + "SystemCapability.ArkUI.ArkUI.Full", + "SystemCapability.ArkUI.ArkUI.Circle", + "SystemCapability.Security.DeviceSecurityLevel", + "SystemCapability.UserIAM.UserAuth.PinAuth" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/mock/Libentry.mock.ets b/ArkUIKit/ButtonList/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..3f2ffde552dedcd3871248d7db8fbfb2ee378b80 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,23 @@ +/* + * 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/ButtonList/entry/src/mock/mock-config.json5 b/ArkUIKit/ButtonList/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..2c7d2ba82b796a2850ced0a277d261d7d7355416 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/mock/mock-config.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. + */ + +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/ohosTest/ets/test/Index.test.ets b/ArkUIKit/ButtonList/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..75a93611cb908c64c38487c7ffda2178dcd8d2cd --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,58 @@ +/* + * 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 } from '@ohos/hypium'; +import { abilityDelegatorRegistry, Driver, ON, Component} from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; + + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + +export default function IndexTest() { + describe('IndexTest', () => { + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info('get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + + it('ButtonIndexTest', 0, async (done: Function) => { + console.info('uitest: ButtonIndexTest begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.id('btn')); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + console.info('uitest: already click'); + await driver.delayMs(1000); + let scrollBar: Component = await driver.findComponent(ON.type('List')); + await scrollBar.scrollToBottom(5000); + console.info('uitest: already scrollToBottom'); + await componentButton.click(); + console.info('uitest: click end'); + await driver.delayMs(1000); + done(); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/ButtonList/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..00cfe9627bd61a31322328fd121fab7f4d2f6d64 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/ohosTest/ets/test/List.test.ets @@ -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 IndexTest from './Index.test'; + +export default function testsuite() { + IndexTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/ohosTest/module.json5 b/ArkUIKit/ButtonList/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5b3d33fe175bb2b544c61442f92949d53fbb47ae --- /dev/null +++ b/ArkUIKit/ButtonList/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/ButtonList/entry/src/ohosTest/syscap.json b/ArkUIKit/ButtonList/entry/src/ohosTest/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..17ee23b5f7d4c4d9a0dba36a2cf2f5184940b62b --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/ohosTest/syscap.json @@ -0,0 +1,15 @@ +{ + "devices": { + "general": ["default","tablet"], + "custom": [ + { + "xts": [ + "SystemCapability.ArkUI.ArkUI.Full", + "SystemCapability.ArkUI.ArkUI.Circle", + "SystemCapability.Security.DeviceSecurityLevel", + "SystemCapability.UserIAM.UserAuth.PinAuth" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/test/List.test.ets b/ArkUIKit/ButtonList/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/test/List.test.ets @@ -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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ButtonList/entry/src/test/LocalUnit.test.ets b/ArkUIKit/ButtonList/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..dcb8c842ef00566bdff6f8b7dd5aaa6cf6c97708 --- /dev/null +++ b/ArkUIKit/ButtonList/entry/src/test/LocalUnit.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 { 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/ButtonList/hvigor/hvigor-config.json5 b/ArkUIKit/ButtonList/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b8fea3f097bd68b0bc4d87de986d2cb7732c1d9b --- /dev/null +++ b/ArkUIKit/ButtonList/hvigor/hvigor-config.json5 @@ -0,0 +1,38 @@ +/* + * 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": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | 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 */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "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/ButtonList/hvigorfile.ts b/ArkUIKit/ButtonList/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3340f07e45ddc5dcadbb87012668555def2e6e0 --- /dev/null +++ b/ArkUIKit/ButtonList/hvigorfile.ts @@ -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. + */ + +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/ButtonList/oh-package.json5 b/ArkUIKit/ButtonList/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..69cb43cba3addcee1840403c67405134a2a9102c --- /dev/null +++ b/ArkUIKit/ButtonList/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. + */ + +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/ButtonList/ohosTest.md b/ArkUIKit/ButtonList/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..a013cfb0791f66894548e54824f977c06a59f9de --- /dev/null +++ b/ArkUIKit/ButtonList/ohosTest.md @@ -0,0 +1,7 @@ +# Navigation 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ------------------- | -------------- |---------------------------------------|-------------| :------- | -------- | +| 测试使用ContentSlot挂载Native侧的文本列表 | 设备正常运行 | 进入示例页面,点击按钮出现文本列表,下拉到页面底部,然后返回 | 文本列表显示正常,滑动页面正常 | 是 | Pass | diff --git a/ArkUIKit/ButtonList/pictures/image01.png b/ArkUIKit/ButtonList/pictures/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..230d395e5a9bb1526da5e1add3e660745c4c5c46 Binary files /dev/null and b/ArkUIKit/ButtonList/pictures/image01.png differ