diff --git a/ArkUIKit/GestureConflict/AppScope/app.json5 b/ArkUIKit/GestureConflict/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..99a7c4e45f22fc5a6ed643360dff373f67b194aa --- /dev/null +++ b/ArkUIKit/GestureConflict/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.samples.gestureconflict", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/GestureConflict/AppScope/resources/base/element/string.json b/ArkUIKit/GestureConflict/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f7b6b8642bbdc34358a7e05e87191130e96f0b46 --- /dev/null +++ b/ArkUIKit/GestureConflict/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "GestureConflict" + } + ] +} diff --git a/ArkUIKit/GestureConflict/AppScope/resources/base/media/background.png b/ArkUIKit/GestureConflict/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/GestureConflict/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/GestureConflict/AppScope/resources/base/media/foreground.png b/ArkUIKit/GestureConflict/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/GestureConflict/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/GestureConflict/AppScope/resources/base/media/layered_image.json b/ArkUIKit/GestureConflict/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/README_zh.md b/ArkUIKit/GestureConflict/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..e75fd9d663381c7a74cfab2d0c8a4d832a585054 --- /dev/null +++ b/ArkUIKit/GestureConflict/README_zh.md @@ -0,0 +1,90 @@ +# 手势冲突处理 + +## 介绍 + +本示例为[手势冲突处理](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/arkts-gesture-events-gesture-judge.md)的配套示例工程。 + +本示例展示了适配手势冲突处理的组件及触发方式。 + +## 效果预览 + +| 首页 | 自定义手势判定 | +|---------------------------------------|-------------------------------------| +| ![](screenshots/Home.jpg) | ![](screenshots/userDefined.jpg) | +| 手势并行动态控制 | 阻止手势参与识别 | +| ![](screenshots/kineticControl.jpg) | ![](screenshots/Stop.jpg) | + + +### 使用说明 + +1. **API 适配场景**: + GestureGroup 模式:Parallel 无冲突用,Serial 有先后依赖用,Exclusive 互斥用。 + 属性范围:priority 按需设(建议 1-5 级),PanGesture 不设 direction 默认全方向。 + +2. **@冲突优先预防**: + 同一组件少绑手势,拆分交互逻辑。 + 父子组件分层:父绑范围手势(如页面滑动),子绑精准手势(如按钮点击)。 + +3. **问题排查**: + 不触发:查组件 enabled、手势绑定、高优先级拦截。 + 触发异常:查 GestureGroup 模式、回调异常逻辑 + +## 工程目录 + +``` +entry/src/main/ets/ +└── pages + └── Index.ets (获取文本界面) +└── Component/CustomGestures + └── CustomGestureDetermination.ets // 自定义手势判定页面 + └── CustomGestures.ets // 自定义手势判定页面片段 +└── Component/GestureAndMotionControl + └── GestureAndMotionControl.ets // 手势并行动态控制页面 + └── GestureControl.ets // 手势并行动态控制页面片段 +└── Component/PreventGestureRecognition + └── PreventGestureRecognition.ets // 阻止手势参与识别页面 + └── PreventIdentification.ets // 阻止手势参与识别页面片段 +``` + +### 具体实现 + +1. **基础单个手势识别**:用系统手势类创建实例,绑定回调并关联组件。 + 点击(TapGesture):设 count(点击次数),onAction 定义逻辑,.gesture () 绑定组件。 + 长按(LongPressGesture):设 duration(触发时间),onActionStart/End 处理始末逻辑。 + 滑动(PanGesture):设 direction(方向),onActionUpdate 获取 offsetX/Y 实现跟随滑动。 +2. **组合手势识别**:用 GestureGroup 按模式管理多手势。 + 并行(Parallel):如捏合 + 旋转,可同时触发。 + 顺序(Serial):如长按后滑动,需先触发前者。 + 互斥(Exclusive):如点击 / 长按,优先识别高优先级手势。 +3. **手势冲突处理**: + 优先级:通过 priority 属性(值越大优先级越高)设置。 + 父子组件:父组件用 gestureMask 控制子组件手势透传。 + 条件过滤:回调中加判断(如有效滑动偏移)避免误触。 + +## 相关权限 + +不涉及 + +## 依赖 + +不涉及 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:RK3568; + +2. 本示例支持API20版本SDK,版本号:6.0.0.36; + +3. 本示例已支持使DevEco Studio 5.0.5 Release (构建版本:5.0.13.100,构建 2025年4月25日)编译运行 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/GestureConflict > .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/GestureConflict/build-profile.json5 b/ArkUIKit/GestureConflict/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3ca5a93fb814017ac4c398aacbdf17b1d8b0a237 --- /dev/null +++ b/ArkUIKit/GestureConflict/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "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/GestureConflict/code-linter.json5 b/ArkUIKit/GestureConflict/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/ArkUIKit/GestureConflict/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/build-profile.json5 b/ArkUIKit/GestureConflict/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/build-profile.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. + */ +{ + "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/GestureConflict/entry/hvigorfile.ts b/ArkUIKit/GestureConflict/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/obfuscation-rules.txt b/ArkUIKit/GestureConflict/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/entry/oh-package.json5 b/ArkUIKit/GestureConflict/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/Component/CustomGestures/CustomGestureDetermination.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/CustomGestures/CustomGestureDetermination.ets new file mode 100644 index 0000000000000000000000000000000000000000..dfceed33635faad0d0e559fc49fc3f5c2be2ca1c --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/CustomGestures/CustomGestureDetermination.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. + */ +// [Start custom_gestures] +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + scroller: Scroller = new Scroller(); + promptAction: PromptAction = this.getUIContext().getPromptAction(); + + build() { + Scroll(this.scroller) { + Column({ space: 8 }) { + // $r('app.string.Drag_instructions') 需要替换为开发者所需的资源文件 + Text($r('app.string.Drag_instructions')).width('100%').fontSize(20).fontColor('0xffdd00') + Stack({ alignContent: Alignment.Center }) { + Column() { + // 模拟上半区和下半区 + Stack().width('200vp').height('100vp').backgroundColor(Color.Red) + Stack().width('200vp').height('100vp').backgroundColor(Color.Blue) + }.width('200vp').height('200vp') + // Stack的下半区是绑定了滑动手势的图像区域。 + // $r('sys.media.ohos_app_icon') 需要替换为开发者所需的资源文件 + Image($r('sys.media.ohos_app_icon')) + .draggable(true) + .onDragStart(()=>{ + // $r('app.string.Allow_dragging_prompt') 需要替换为开发者所需的资源文件 + this.promptAction.showToast({ message: $r('app.string.Allow_dragging_prompt') }); + }) + .width('200vp').height('200vp') + // Stack的上半区是绑定了长按手势的浮动区域。 + Stack() { + } + .width('200vp') + .height('200vp') + .hitTestBehavior(HitTestMode.Transparent) + .gesture(GestureGroup(GestureMode.Parallel, + LongPressGesture() + .onAction((event: GestureEvent) => { + // $r('app.string.Stop_dragging_prompt') 需要替换为开发者所需的资源文件 + this.promptAction.showToast({ message: $r('app.string.Stop_dragging_prompt') }); + }) + .tag('longpress') + )) + .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => { + // 如果是长按类型手势,判断点击的位置是否在上半区 + if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) { + if (event.fingerList.length > 0 && event.fingerList[0].localY < 100) { + return GestureJudgeResult.CONTINUE; + } else { + return GestureJudgeResult.REJECT; + } + }; + return GestureJudgeResult.CONTINUE; + }) + }.width('100%') + }.width('100%') + } + } +} +// [End custom_gestures] \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/Component/CustomGestures/CustomGestures.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/CustomGestures/CustomGestures.ets new file mode 100644 index 0000000000000000000000000000000000000000..1da6f46b64627d42f5487144f04121dd9f90f004 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/CustomGestures/CustomGestures.ets @@ -0,0 +1,86 @@ +/* + * 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 { PromptAction } from '@kit.ArkUI'; +@Entry +@Component +struct CustomGestures { + scroller: Scroller = new Scroller(); + build() { + Scroll(this.scroller) { + Column({ space: 8 }) { + // $r('app.string.Drag_instructions') 需要替换为开发者所需的资源文件 + Text($r('app.string.Drag_instructions')).width('100%').fontSize(20).fontColor('0xffdd00') + Stack({ alignContent: Alignment.Center }) { + Column() { + // 模拟上半区和下半区 + Stack().width('200vp').height('100vp').backgroundColor(Color.Red) + Stack().width('200vp').height('100vp').backgroundColor(Color.Blue) + }.width('200vp').height('200vp') + + + // [Start component_dragging] + // $r('sys.media.ohos_app_icon') 需要替换为开发者所需的资源文件 + Image($r('sys.media.ohos_app_icon')) + .draggable(true) + .onDragStart(()=>{ + // [StartExclude component_dragging] + let promptAction: PromptAction = this.getUIContext().getPromptAction(); + // [EndExclude component_dragging] + // $r('app.string.Allow_dragging_prompt') 需要替换为开发者所需的资源文件 + promptAction.showToast({ message: $r('app.string.Allow_dragging_prompt') }); + }) + .width('200vp').height('200vp') + // [End component_dragging] + + + + // [Start set_gestures] + Stack() {} + .width('200vp') + .height('200vp') + .hitTestBehavior(HitTestMode.Transparent) + .gesture(GestureGroup(GestureMode.Parallel, + LongPressGesture() + .onAction((event: GestureEvent) => { + // [StartExclude set_gestures] + let promptAction: PromptAction = this.getUIContext().getPromptAction(); + // [EndExclude set_gestures] + // $r('app.string.Stop_dragging_prompt') 需要替换为开发者所需的资源文件 + promptAction.showToast({ message: $r('app.string.Stop_dragging_prompt') }); + }) + .tag('longpress') + )) + // [End set_gestures] + + // [Start set_interception] + .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => { + // 如果是长按类型手势,判断点击的位置是否在上半区 + if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) { + if (event.fingerList.length > 0 && event.fingerList[0].localY < 100) { + return GestureJudgeResult.CONTINUE; + } else { + return GestureJudgeResult.REJECT; + } + }; + return GestureJudgeResult.CONTINUE; + }) + // [End set_interception] + + }.width('100%') + }.width('100%') + } + } +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/Component/GestureAndMotionControl/GestureAndMotionControl.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/GestureAndMotionControl/GestureAndMotionControl.ets new file mode 100644 index 0000000000000000000000000000000000000000..2e05db7be5595914a1260290f74db8a0d71c9db0 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/GestureAndMotionControl/GestureAndMotionControl.ets @@ -0,0 +1,153 @@ +/* + * 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 gesture_motioncontrol] +// xxx.ets +@Entry +@Component +struct FatherControlChild { + scroller: Scroller = new Scroller(); + scroller2: Scroller = new Scroller(); + private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + private childRecognizer: GestureRecognizer = new GestureRecognizer(); + private currentRecognizer: GestureRecognizer = new GestureRecognizer(); + private lastOffset: number = 0; + + build() { + Stack({ alignContent: Alignment.TopStart }) { + Scroll(this.scroller) { // 外部滚动容器 + Column() { + Text('Scroll Area') + .width('90%') + .height(150) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) + Scroll(this.scroller2) { // 内部滚动容器 + Column() { + Text('Scroll Area2') + .width('90%') + .height(150) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) + Column() { + ForEach(this.arr, (item: number) => { + Text(item.toString()) + .width('90%') + .height(150) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) + }, (item: string) => item) + }.width('100%') + } + } + .id('inner') + .width('100%') + .height(800) + }.width('100%') + } + .id('outer') + .height(600) + .scrollable(ScrollDirection.Vertical) // 滚动方向纵向 + .scrollBar(BarState.On) // 滚动条常驻显示 + .scrollBarColor(Color.Gray) // 滚动条颜色 + .scrollBarWidth(10) // 滚动条宽度 + .edgeEffect(EdgeEffect.None) + .shouldBuiltInRecognizerParallelWith((current: GestureRecognizer, others: Array) => { + for (let i = 0; i < others.length; i++) { + let target = others[i].getEventTargetInfo(); + if (target.getId() == 'inner' && others[i].isBuiltIn() && + others[i].getType() == GestureControl.GestureType.PAN_GESTURE) { // 找到将要组成并行手势的识别器 + this.currentRecognizer = current; // 保存当前组件的识别器 + this.childRecognizer = others[i]; // 保存将要组成并行手势的识别器 + return others[i]; // 返回和当前手势将要组成并行手势的识别器 + } + } + return undefined; + }) + .onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer, + others: Array) => { // 在识别器即将要成功时,根据当前组件状态,设置识别器使能状态 + let target = current.getEventTargetInfo(); + if (target && target.getId() == 'outer' && current.isBuiltIn() && + current.getType() == GestureControl.GestureType.PAN_GESTURE) { + for (let i = 0; i < others.length; i++) { + let target = others[i].getEventTargetInfo() as ScrollableTargetInfo; + if (target instanceof ScrollableTargetInfo && target.getId() == 'inner') { // 找到响应链上对应并行的识别器 + let panEvent = event as PanGestureEvent; + this.childRecognizer.setEnabled(true); + this.currentRecognizer.setEnabled(false); + if (target.isEnd()) { // 根据当前组件状态以及移动方向动态控制识别器使能状态 + if (panEvent && panEvent.offsetY < 0) { + this.childRecognizer.setEnabled(false); + this.currentRecognizer.setEnabled(true); + } + } else if (target.isBegin()) { + if (panEvent.offsetY > 0) { + this.childRecognizer.setEnabled(false); + this.currentRecognizer.setEnabled(true); + } + } + } + } + } + return GestureJudgeResult.CONTINUE; + }) + .parallelGesture( // 绑定一个Pan手势作为动态控制器 + PanGesture() + .onActionUpdate((event: GestureEvent) => { + if (this.childRecognizer?.getState() != GestureRecognizerState.SUCCESSFUL || + this.currentRecognizer?.getState() != GestureRecognizerState.SUCCESSFUL) { // 如果识别器状态不是SUCCESSFUL,则不做控制 + return; + } + let target = this.childRecognizer.getEventTargetInfo() as ScrollableTargetInfo; + let currentTarget = this.currentRecognizer.getEventTargetInfo() as ScrollableTargetInfo; + if (target instanceof ScrollableTargetInfo && currentTarget instanceof ScrollableTargetInfo) { + this.childRecognizer.setEnabled(true); + this.currentRecognizer.setEnabled(false); + if (target.isEnd()) { // 在移动过程中实时根据当前组件状态,控制识别器的开闭状态 + if ((event.offsetY - this.lastOffset) < 0) { + this.childRecognizer.setEnabled(false); + if (currentTarget.isEnd()) { + this.currentRecognizer.setEnabled(false); + } else { + this.currentRecognizer.setEnabled(true); + }; + }; + } else if (target.isBegin()) { + if ((event.offsetY - this.lastOffset) > 0) { + this.childRecognizer.setEnabled(false) + if (currentTarget.isBegin()) { + this.currentRecognizer.setEnabled(false); + } else { + this.currentRecognizer.setEnabled(true); + }; + }; + }; + }; + this.lastOffset = event.offsetY; + }) + ) + }.width('100%').height('100%').backgroundColor(0xDCDCDC) + } +} +// [End gesture_motioncontrol] \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/Component/GestureAndMotionControl/GestureControl.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/GestureAndMotionControl/GestureControl.ets new file mode 100644 index 0000000000000000000000000000000000000000..46a2b02048a1898c6f08c2a4826fe26788717d86 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/GestureAndMotionControl/GestureControl.ets @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Entry +@Component +struct GestureControlGroup { + scroller: Scroller = new Scroller(); + scroller2: Scroller = new Scroller(); + private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + private childRecognizer: GestureRecognizer = new GestureRecognizer(); + private currentRecognizer: GestureRecognizer = new GestureRecognizer(); + private lastOffset: number = 0; + + build() { + Stack({ alignContent: Alignment.TopStart }) { + Scroll(this.scroller) { // 外部滚动容器 + Column() { + Text('Scroll Area') + .width('90%') + .height(150) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) + Scroll(this.scroller2) { // 内部滚动容器 + Column() { + Text('Scroll Area2') + .width('90%') + .height(150) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) + Column() { + ForEach(this.arr, (item: number) => { + Text(item.toString()) + .width('90%') + .height(150) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.Center) + .margin({ top: 10 }) + }, (item: string) => item) + }.width('100%') + } + } + .id('inner') + .width('100%') + .height(800) + }.width('100%') + } + .id('outer') + .height(600) + .scrollable(ScrollDirection.Vertical) // 滚动方向纵向 + .scrollBar(BarState.On) // 滚动条常驻显示 + .scrollBarColor(Color.Gray) // 滚动条颜色 + .scrollBarWidth(10) // 滚动条宽度 + .edgeEffect(EdgeEffect.None) + + + // [Start gesture_simultaneously] + .shouldBuiltInRecognizerParallelWith((current: GestureRecognizer, others: Array) => { + for (let i = 0; i < others.length; i++) { + let target = others[i].getEventTargetInfo(); + if (target.getId() == 'inner' && others[i].isBuiltIn() && others[i].getType() == GestureControl.GestureType.PAN_GESTURE) { // 找到将要组成并行手势的识别器 + this.currentRecognizer = current; // 保存当前组件的识别器 + this.childRecognizer = others[i]; // 保存将要组成并行手势的识别器 + return others[i]; // 返回和当前手势将要组成并行手势的识别器 + }; + }; + return undefined; + }) + // [End gesture_simultaneously] + + + // [Start gesture_openingclosing] + .onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer, + others: Array) => { // 在识别器即将要成功时,根据当前组件状态,设置识别器使能状态 + let target = current.getEventTargetInfo(); + if (target && target.getId() == 'outer' && current.isBuiltIn() && current.getType() == GestureControl.GestureType.PAN_GESTURE) { + for (let i = 0; i < others.length; i++) { + let target = others[i].getEventTargetInfo() as ScrollableTargetInfo; + if (target instanceof ScrollableTargetInfo && target.getId() == 'inner') { // 找到响应链上对应并行的识别器 + let panEvent = event as PanGestureEvent; + this.childRecognizer.setEnabled(true); + this.currentRecognizer.setEnabled(false); + if (target.isEnd()) { // 根据当前组件状态以及移动方向动态控制识别器使能状态 + if (panEvent && panEvent.offsetY < 0) { + this.childRecognizer.setEnabled(false); + this.currentRecognizer.setEnabled(true); + }; + } else if (target.isBegin()) { + if (panEvent.offsetY > 0) { + this.childRecognizer.setEnabled(false); + this.currentRecognizer.setEnabled(true); + }; + }; + }; + }; + }; + return GestureJudgeResult.CONTINUE; + }) + // [End gesture_openingclosing] + + // [Start listening_gestures] + .parallelGesture( // 绑定一个Pan手势作为动态控制器 + PanGesture() + .onActionUpdate((event: GestureEvent)=>{ + if (this.childRecognizer.getState() != GestureRecognizerState.SUCCESSFUL || + this.currentRecognizer.getState() != GestureRecognizerState.SUCCESSFUL) { // 如果识别器状态不是SUCCESSFUL,则不做控制 + return; + }; + let target = this.childRecognizer.getEventTargetInfo() as ScrollableTargetInfo; + let currentTarget = this.currentRecognizer.getEventTargetInfo() as ScrollableTargetInfo; + if (target instanceof ScrollableTargetInfo && currentTarget instanceof ScrollableTargetInfo) { + this.childRecognizer.setEnabled(true); + this.currentRecognizer.setEnabled(false); + if (target.isEnd()) { // 在移动过程中实时根据当前组件状态,控制识别器的开闭状态 + if ((event.offsetY - this.lastOffset) < 0) { + this.childRecognizer.setEnabled(false); + if (currentTarget.isEnd()) { + this.currentRecognizer.setEnabled(false); + } else { + this.currentRecognizer.setEnabled(true); + }; + }; + } else if (target.isBegin()) { + if ((event.offsetY - this.lastOffset) > 0) { + this.childRecognizer.setEnabled(false); + if (currentTarget.isBegin()) { + this.currentRecognizer.setEnabled(false); + } else { + this.currentRecognizer.setEnabled(true); + }; + }; + }; + }; + this.lastOffset = event.offsetY; + }) + ) + // [End listening_gestures] + + }.width('100%').height('100%').backgroundColor(0xDCDCDC) + } +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/Component/PreventGestureRecognition/PreventGestureRecognition.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/PreventGestureRecognition/PreventGestureRecognition.ets new file mode 100644 index 0000000000000000000000000000000000000000..6d45c636fb47498c265b45cbfbfb78cef8e5ac9e --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/PreventGestureRecognition/PreventGestureRecognition.ets @@ -0,0 +1,254 @@ +/* + * 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 gesture_recognition] +@Entry +@ComponentV2 +struct Index { + @Local progress: number = 496000; // 初始进度,秒 + @Local total: number = 27490000; // 总时长,秒 + @Local currentWidth: string = '100%'; + @Local currentHeight: string = '100%'; + private currentPosX: number = 0; + private currentPosY: number = 0; + private currentFullScreenState: boolean = true; + private normalPlayTimer: number = -1; + private isPlaying: boolean = true; + private fastForwardTimer: number = -1; + private context = this.getUIContext().getHostContext() + + aboutToAppear(): void { + // 启动一个周期性定时器每隔一秒刷新一次进度 + this.startNormalPlayTimer(); + }; + + startNormalPlayTimer(): void { + if (this.normalPlayTimer != -1) { + this.stopNormalPlayTimer() + }; + this.normalPlayTimer = setInterval(() => { + this.progress = this.progress + 1000 + }, 1000); + }; + + stopNormalPlayTimer(): void { + if (this.normalPlayTimer == -1) { + return; + }; + clearInterval(this.normalPlayTimer); + this.normalPlayTimer = -1; + }; + + startFastForwardTimer(): void { + if (this.fastForwardTimer != -1) { + this.stopFastForwardTimer(); + }; + this.fastForwardTimer = setInterval(() => { + this.progress = this.progress + 100000; + }, 100); + }; + + stopFastForwardTimer(): void { + if (this.fastForwardTimer == -1) { + return; + }; + clearInterval(this.fastForwardTimer); + this.fastForwardTimer = -1; + }; + + showMessage(message: string): void { + this.getUIContext().getPromptAction().showToast({ message: message, alignment: Alignment.Center }); + }; + + resetPosInfo(): void { + this.currentPosX = 0; + this.currentPosY = 0; + }; + + toggleFullScreenState(): void { + this.currentFullScreenState = !this.currentFullScreenState; + if (this.currentFullScreenState) { + this.currentWidth = '100%'; + this.currentHeight = '100%'; + } else { + this.currentWidth = '100%'; + this.currentHeight = '50%'; + }; + // $r('app.string.Play_full_screen') 需要替换为开发者所需的资源文件 + // $r('app.string.Exit_play_full_screen') 需要替换为开发者所需的资源文件 + this.showMessage(this.currentFullScreenState + ? this.context!.resourceManager.getStringSync($r('app.string.Play_full_screen').id) + : this.context!.resourceManager.getStringSync($r('app.string.Exit_play_full_screen').id)); + }; + + togglePlayAndPause(): void { + this.isPlaying = !this.isPlaying; + if (!this.isPlaying) { + this.stopNormalPlayTimer(); + } else { + // 重新启动 + this.startNormalPlayTimer(); + }; + // $r('app.string.stop_playing') 需要替换为开发者所需的资源文件 + // $r('app.string.Continue_playing') 需要替换为开发者所需的资源文件 + this.showMessage(this.isPlaying + ? this.context!.resourceManager.getStringSync($r('app.string.stop_playing').id) + : this.context!.resourceManager.getStringSync($r('app.string.Continue_playing').id)); + }; + + doFastForward(start: boolean): void { + if (!start) { // 停止快进,恢复正常播放 + this.stopFastForwardTimer(); + this.startNormalPlayTimer(); + // $r('app.string.Cancel_FastForwarding') 需要替换为开发者所需的资源文件 + this.showMessage( + this.context!.resourceManager.getStringSync($r('app.string.Cancel_FastForwarding').id)); + return; + }; + + this.stopNormalPlayTimer(); + this.startFastForwardTimer(); + // $r('app.string.Start_FastForwarding') 需要替换为开发者所需的资源文件 + this.showMessage( + this.context!.resourceManager.getStringSync($r('app.string.Start_FastForwarding').id)); + }; + + updateBrightness(start: boolean, event: BaseGestureEvent): void { + let newY = event.fingerList[0].localY; + if (start) { + this.currentPosY = newY; + // $r('app.string.Start_adjusting_brightness') 需要替换为开发者所需的资源文件 + this.showMessage(this.context!.resourceManager + .getStringSync($r('app.string.Start_adjusting_brightness').id)); + return; + }; + let offsetY = newY - this.currentPosY; + if (Math.abs(offsetY) > 10) { + // $r('app.string.Reduce_brightness') 需要替换为开发者所需的资源文件 + // $r('app.string.Increase_brightness') 需要替换为开发者所需的资源文件 + this.showMessage((offsetY > 0) + ? this.context!.resourceManager.getStringSync($r('app.string.Reduce_brightness').id) + : this.context!.resourceManager.getStringSync($r('app.string.Increase_brightness').id) ) + this.currentPosY = newY; + }; + }; + + updateProgress(start: boolean, event: BaseGestureEvent): void { + let newX = event.fingerList[0].localX; + if (start) { + this.currentPosX = newX; + // $r('app.string.Adjust_schedule') 需要替换为开发者所需的资源文件 + this.showMessage(this.context!.resourceManager + .getStringSync($r('app.string.Adjust_schedule').id)); + return; + }; + let offsetX = newX - this.currentPosX; + this.progress = Math.floor(this.progress + offsetX * 10000); + this.currentPosX = newX; + }; + + build() { + Stack({ alignContent: Alignment.Center }) { + Column() { + Column() { + // $r('app.string.Playback_progress') 需要替换为开发者所需的资源文件 + Text(this.context!.resourceManager.getStringSync($r('app.string.Playback_progress').id) + this.progress) + } + .width('100%').height('90%') + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { + Slider({ + value: this.progress, + min: 0, + max: this.total, + style: SliderStyle.OutSet + }) + .onChange((value: number, mode: SliderChangeMode) => { + this.progress = value; + }) + .id('progress_layer') + .onTouchTestDone((event, allRecognizers: Array) => { + for (let i = 0; i < allRecognizers.length; i++) { + let recognizer = allRecognizers[i]; + let inspectorInfo = recognizer.getEventTargetInfo().getId(); + if (inspectorInfo !== 'progress_layer') { + // 用户操作到进度条区域时,禁用掉所有非progress_layer上的手势 + recognizer.preventBegin(); + }; + }; + }) + .margin({ left: 5 }) + .trackColor(Color.Red) + .blockColor(Color.Yellow) + .selectedColor(Color.Orange) + .trackThickness(2) + .flexShrink(1) + .flexGrow(1) + } + .flexGrow(1) + .flexShrink(1) + .id('id_progress_view') + } + } + .id('video_layer') + .backgroundColor('#E0E0E0') + .gesture( + GestureGroup(GestureMode.Exclusive, + PanGesture({ direction: PanDirection.Vertical, distance: 10 }) + .tag('pan_for_brightness_control') + .onActionStart((event) => { + this.updateBrightness(true, event); + }) + .onActionUpdate((event) => { + this.updateBrightness(false, event); + }), + PanGesture({ direction: PanDirection.Horizontal, distance: 10 }) + .tag('pan_for_play_progress_control') + .onActionStart((event) => { + this.updateProgress(true, event); + }) + .onActionUpdate((event) => { + this.updateProgress(false, event); + }), + + LongPressGesture() + .tag('long_press_for_fast_forward_control') + .onAction(() => { + this.doFastForward(true); // 开始快进 + }) + .onActionEnd(() => { + this.doFastForward(false); // 停止快进 + }) + .onActionCancel(() => { + this.doFastForward(false); + }), + + TapGesture({ count: 2 }) + .tag('double_tap_on_video') + .onAction(() => { + this.toggleFullScreenState(); + }), + + TapGesture() + .tag('single_tap_on_video') + .onAction(() => { + this.togglePlayAndPause(); + }) + ) + ) + .width(this.currentWidth) + .height(this.currentHeight) + } +} +// [End gesture_recognition] \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/Component/PreventGestureRecognition/PreventIdentification.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/PreventGestureRecognition/PreventIdentification.ets new file mode 100644 index 0000000000000000000000000000000000000000..118ddc4b5f7a9ce0a428e710727042c2618c9f9b --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/Component/PreventGestureRecognition/PreventIdentification.ets @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Entry +@ComponentV2 +struct PreventIdentification { + @Local progress: number = 496000; // 初始进度,秒 + @Local total: number = 27490000; // 总时长,秒 + @Local currentWidth: string = '100%'; + @Local currentHeight: string = '100%'; + private currentPosX: number = 0; + private currentPosY: number = 0; + private currentFullScreenState: boolean = true; + private normalPlayTimer: number = -1; + private isPlaying: boolean = true; + private fastForwardTimer: number = -1; + private context = this.getUIContext().getHostContext() + + aboutToAppear(): void { + // 启动一个周期性定时器每隔一秒刷新一次进度 + this.startNormalPlayTimer(); + }; + + startNormalPlayTimer(): void { + if (this.normalPlayTimer != -1) { + this.stopNormalPlayTimer(); + }; + this.normalPlayTimer = setInterval(() => { + this.progress = this.progress + 1000; + }, 1000); + }; + + stopNormalPlayTimer(): void { + if (this.normalPlayTimer == -1) { + return; + }; + clearInterval(this.normalPlayTimer); + this.normalPlayTimer = -1; + }; + + startFastForwardTimer(): void { + if (this.fastForwardTimer != -1) { + this.stopFastForwardTimer(); + }; + this.fastForwardTimer = setInterval(() => { + this.progress = this.progress + 100000; + }, 100); + }; + + stopFastForwardTimer(): void { + if (this.fastForwardTimer == -1) { + return; + }; + clearInterval(this.fastForwardTimer); + this.fastForwardTimer = -1; + }; + + showMessage(message: string): void { + this.getUIContext().getPromptAction().showToast({ message: message, alignment: Alignment.Center }); + }; + + resetPosInfo(): void { + this.currentPosX = 0; + this.currentPosY = 0; + }; + + toggleFullScreenState(): void { + this.currentFullScreenState = !this.currentFullScreenState; + if (this.currentFullScreenState) { + this.currentWidth = '100%'; + this.currentHeight = '100%'; + } else { + this.currentWidth = '100%'; + this.currentHeight = '50%'; + }; + // $r('app.string.Play_full_screen') 需要替换为开发者所需的资源文件 + // $r('app.string.Exit_play_full_screen') 需要替换为开发者所需的资源文件 + this.showMessage(this.currentFullScreenState + ? this.context!.resourceManager.getStringSync($r('app.string.Play_full_screen').id) + : this.context!.resourceManager.getStringSync($r('app.string.Exit_play_full_screen').id)); + }; + + togglePlayAndPause(): void { + this.isPlaying = !this.isPlaying; + if (!this.isPlaying) { + this.stopNormalPlayTimer(); + } else { + // 重新启动 + this.startNormalPlayTimer(); + }; + // $r('app.string.stop_playing') 需要替换为开发者所需的资源文件 + // $r('app.string.Continue_playing') 需要替换为开发者所需的资源文件 + this.showMessage(this.isPlaying + ? this.context!.resourceManager.getStringSync($r('app.string.stop_playing').id) + : this.context!.resourceManager.getStringSync($r('app.string.Continue_playing').id)); + }; + + doFastForward(start: boolean): void { + if (!start) { // 停止快进,恢复正常播放 + this.stopFastForwardTimer(); + this.startNormalPlayTimer(); + // $r('app.string.Cancel_FastForwarding') 需要替换为开发者所需的资源文件 + this.showMessage( + this.context!.resourceManager.getStringSync($r('app.string.Cancel_FastForwarding').id)); + return; + }; + + this.stopNormalPlayTimer(); + this.startFastForwardTimer(); + // $r('app.string.Start_FastForwarding') 需要替换为开发者所需的资源文件 + this.showMessage( + this.context!.resourceManager.getStringSync($r('app.string.Start_FastForwarding').id)); + }; + + updateBrightness(start: boolean, event: BaseGestureEvent): void { + let newY = event.fingerList[0].localY; + if (start) { + this.currentPosY = newY; + // $r('app.string.Start_adjusting_brightness') 需要替换为开发者所需的资源文件 + this.showMessage(this.context!.resourceManager + .getStringSync($r('app.string.Start_adjusting_brightness').id)); + return; + }; + let offsetY = newY - this.currentPosY; + if (Math.abs(offsetY) > 10) { + // $r('app.string.Reduce_brightness') 需要替换为开发者所需的资源文件 + // $r('app.string.Increase_brightness') 需要替换为开发者所需的资源文件 + this.showMessage((offsetY > 0) + ? this.context!.resourceManager.getStringSync($r('app.string.Reduce_brightness').id) + : this.context!.resourceManager.getStringSync($r('app.string.Increase_brightness').id) ) + this.currentPosY = newY; + }; + }; + + updateProgress(start: boolean, event: BaseGestureEvent): void { + let newX = event.fingerList[0].localX; + if (start) { + this.currentPosX = newX; + // $r('app.string.Adjust_schedule') 需要替换为开发者所需的资源文件 + this.showMessage(this.context!.resourceManager + .getStringSync($r('app.string.Adjust_schedule').id)); + return; + }; + let offsetX = newX - this.currentPosX; + this.progress = Math.floor(this.progress + offsetX * 10000); + this.currentPosX = newX; + }; + + build() { + Stack({ alignContent: Alignment.Center }) { + Column() { + Column() { + // $r('app.string.Playback_progress') 需要替换为开发者所需的资源文件 + Text(this.context!.resourceManager.getStringSync($r('app.string.Playback_progress').id) + this.progress) + } + .width('100%').height('90%') + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { + Slider({ + value: this.progress, + min: 0, + max: this.total, + style: SliderStyle.OutSet + }) + .onChange((value: number, mode: SliderChangeMode) => { + this.progress = value; + }) + .id('progress_layer') + + + + // [Start disable_gesturetype] + .onTouchTestDone((event, recognizers) => { + for (let i = 0; i < recognizers.length; i++) { + let recognizer = recognizers[i]; + // 根据类型禁用所有滑动手势 + if (recognizer.getType() == GestureControl.GestureType.PAN_GESTURE) { + recognizer.preventBegin(); + }; + }; + }) + // [End disable_gesturetype] + + // [Start component_disabled] + .onTouchTestDone((event, recognizers) => { + for (let i = 0; i < recognizers.length; i++) { + let recognizer = recognizers[i]; + // 禁用掉标识为myID的组件上的所有手势 + if (recognizer.getEventTargetInfo().getId() == 'myID') { + recognizer.preventBegin(); + }; + }; + }) + // [End component_disabled] + + // [Start builtIn_gestureDisable] + .onTouchTestDone((event, recognizers) => { + for (let i = 0; i < recognizers.length; i++) { + let recognizer = recognizers[i]; + // 禁用掉所有系统内置的手势 + if (recognizer.isBuiltIn()) { + recognizer.preventBegin(); + }; + }; + }) + // [End builtIn_gestureDisable] + + .margin({ left: 5 }) + .trackColor(Color.Red) + .blockColor(Color.Yellow) + .selectedColor(Color.Orange) + .trackThickness(2) + .flexShrink(1) + .flexGrow(1) + } + .flexGrow(1) + .flexShrink(1) + .id('id_progress_view') + } + } + .id('video_layer') + .backgroundColor('#E0E0E0') + .gesture( + GestureGroup(GestureMode.Exclusive, + PanGesture({ direction: PanDirection.Vertical, distance: 10 }) + .tag('pan_for_brightness_control') + .onActionStart((event) => { + this.updateBrightness(true, event); + }) + .onActionUpdate((event) => { + this.updateBrightness(false, event); + }), + PanGesture({ direction: PanDirection.Horizontal, distance: 10 }) + .tag('pan_for_play_progress_control') + .onActionStart((event) => { + this.updateProgress(true, event); + }) + .onActionUpdate((event) => { + this.updateProgress(false, event); + }), + + LongPressGesture() + .tag('long_press_for_fast_forward_control') + .onAction(() => { + this.doFastForward(true); // 开始快进 + }) + .onActionEnd(() => { + this.doFastForward(false); // 停止快进 + }) + .onActionCancel(() => { + this.doFastForward(false); + }), + + TapGesture({ count: 2 }) + .tag('double_tap_on_video') + .onAction(() => { + this.toggleFullScreenState(); + }), + + TapGesture() + .tag('single_tap_on_video') + .onAction(() => { + this.togglePlayAndPause(); + }) + ) + ) + .width(this.currentWidth) + .height(this.currentHeight) + } +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..98182799de1294d4c21194646a0c30eff08aea33 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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 { + // Main window is created, set main page for this ability + 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 { + // 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/GestureConflict/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ce6449f0e91914e73d4502c9f2e8e9a395ea4b1 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/ets/pages/Index.ets b/ArkUIKit/GestureConflict/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..0947f537ad97db1d5ffaa95d8fbfbc069d64a9b7 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,98 @@ +/* + * 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 router from '@ohos.router'; + +interface listItem { + router?: string; + name: string; + description?: string; +}; +let demandList: listItem[] = [ + { + name: 'Custom gesture recognition', + description: 'The application can independently decide whether to intercept this gesture, causing the gesture recognition to fail, thereby leaving the chance of successful recognition to other gestures.', + router: 'Component/CustomGestures/CustomGestureDetermination' + }, + { + name: 'Gesture and motion control', + description: 'Gesture and motion control refers to the situation where the gesture has been successfully recognized, but the developer can still control whether the gesture callback can respond by calling the API interface.', + router: 'Component/GestureAndMotionControl/GestureAndMotionControl' + }, + { + name: 'Preventing gesture participation in recognition', + description: 'When the user presses, by controlling the participation status of the gesture recognizer in the response chain, efficient dynamic intervention of gesture processing is achieved.', + router: 'Component/PreventGestureRecognition/PreventGestureRecognition' + } +]; + +@Entry +@Component +struct Index { + @State bgColor: ResourceColor = '#39b5fa'; + + build() { + Column() { + Column() { + List({ space: 20, initialIndex: 0 }) { + ForEach(demandList, (listitem: listItem, index: number) => { + ListItem() { + Column({ space: 10 }) { + Text(listitem.name) + .fontSize(20) + .fontColor(this.bgColor) + .maxLines(1) + + Text(listitem.description) + .width('100%') + } + .margin({ bottom: index >= demandList.length - 1 ? 100 : 0 }) + .padding({ + top: '3%', + right: '10.00%', + bottom: '5%', + left: '10.00%' + }) + .width('100%') + .constraintSize({ minHeight: 100 }) + .borderRadius(10) + .backgroundColor(0xFFFFFF) + .onClick(() => { + if (!!listitem.router) { + this.getUIContext().getRouter().pushUrl({ url: listitem.router }) + }; + }) + } + }) + } + .listDirection(Axis.Vertical) // 排列方向 + .scrollBar(BarState.Off) + .friction(0.6) + .divider({ + strokeWidth: 2, + color: 0xFFFFFF, + startMargin: 20, + endMargin: 20 + }) // 每行之间的分界线 + .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring + .width('90%') + } + .width('100%') + .height('100%') + .backgroundColor('#fff4f3f3') + .padding({ top: 5 }) + } + } +} diff --git a/ArkUIKit/GestureConflict/entry/src/main/module.json5 b/ArkUIKit/GestureConflict/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8930831ba2f2326ee0eabe8a6eac4a9c44ad5c96 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/module.json5 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "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/GestureConflict/entry/src/main/resources/base/element/color.json b/ArkUIKit/GestureConflict/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/entry/src/main/resources/base/element/float.json b/ArkUIKit/GestureConflict/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/entry/src/main/resources/base/element/string.json b/ArkUIKit/GestureConflict/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..05a6cc74adb97a08e01185d752c2776e0ad17bf0 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/resources/base/element/string.json @@ -0,0 +1,72 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "Drag_instructions", + "value": "包括上下两层组件,上层组件绑定长按手势,下层组件绑定拖拽。其中上层组件下半区域绑定手势拦截,使该区域响应下层拖拽手势。" + }, + { + "name": "Allow_dragging_prompt", + "value": "Drag 下半区蓝色区域,Image响应" + }, + { + "name": "Stop_dragging_prompt", + "value": "LongPressGesture 长按上半区 红色区域,红色区域响应" + }, + { + "name": "Playback_progress", + "value": "播放进度" + }, + { + "name": "Play_full_screen", + "value": "全屏播放" + }, + { + "name": "Exit_play_full_screen", + "value": "取消全屏播放" + }, + { + "name": "stop_playing", + "value": "暂停播放" + }, + { + "name": "Continue_playing", + "value": "继续播放" + }, + { + "name": "Cancel_FastForwarding", + "value": "取消快进" + }, + { + "name": "Start_FastForwarding", + "value": "开始快进" + }, + { + "name": "Start_adjusting_brightness", + "value": "开始调整 亮度" + }, + { + "name": "Reduce_brightness", + "value": "降低亮度" + }, + { + "name": "Increase_brightness", + "value": "提高亮度" + }, + { + "name": "Adjust_schedule", + "value": "开始调整 进度" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/background.png b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/GestureConflict/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/GestureConflict/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/GestureConflict/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/GestureConflict/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..5b2ca389b9aa67dc4230e85a5bf2bac574411662 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,11 @@ +{ + "src": [ + "pages/Index", + "Component/CustomGestures/CustomGestureDetermination", + "Component/GestureAndMotionControl/GestureAndMotionControl", + "Component/PreventGestureRecognition/PreventGestureRecognition", + "Component/CustomGestures/CustomGestures", + "Component/GestureAndMotionControl/GestureControl", + "Component/PreventGestureRecognition/PreventIdentification" + ] +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/main/resources/dark/element/color.json b/ArkUIKit/GestureConflict/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/GestureConflict/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/GestureConflict/entry/src/mock/mock-config.json5 b/ArkUIKit/GestureConflict/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..323d1d611fecf4ecb751976e3a71500b3712a445 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * 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. + */ +{ +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7f30942b81554a399e89aa253c7089eca4f8d8d1 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/Index.test.ets b/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..49304b59c857d0a71ebb67845ea7c97a498adf16 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,137 @@ +/* + * 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 '@ohos.hilog'; + +// HiLog通常需要domain, tag等参数 +const DOMAIN = 0x0001; +const TAG = 'Sample_gestureconflict'; + +const delegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let driver: Driver; +let want: Want; + +export default function GestureConflict() { + describe('GestureConflict', () => { + beforeAll(async () => { + // 启动应用 + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + driver = Driver.create(); + await driver.delayMs(2000); // 增加初始等待时间 + + // 验证当前页面是否正确 + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(DOMAIN, TAG,'get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }); + + /** + * @tc.number GestureConflict_001 + * @tc.name testHomePageLoad + * @tc.desc 测试首页加载是否成功 + */ + it('testHomePageLoad', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG,'GestureConflict: testHomePageLoad begin'); + + // 验证列表项存在 - 使用首页中实际存在的文本 + const listItem = await driver.findComponent(ON.text('Custom gesture recognition')); + hilog.info(DOMAIN, TAG,`GestureConflict: list item found: ${listItem !== null}`); + expect(listItem === null).assertFalse(); + + // 验证列表存在 + const list = await driver.findComponent(ON.type('List')); + hilog.info(DOMAIN, TAG,`GestureConflict: list found: ${list !== null}`); + expect(list === null).assertFalse(); + + hilog.info(DOMAIN, TAG,'GestureConflict: testHomePageLoad end'); + done(); + }); + + /** + * @tc.number GestureConflict_002 + * @tc.name testNavigationToDetailPage + * @tc.desc 测试页面 长按拖动 + */ + it('testNavigationToDetailPage', 0, async (done: Function) => { + // 查找并点击第一个列表项 + const targetItem = await driver.findComponent(ON.text('Custom gesture recognition')); + if (targetItem !== null) { + await targetItem.click(); + // 等待目标页面加载 + await driver.delayMs(2000); + // 返回首页 + await driver.pressBack(); + await driver.delayMs(1000); + } + done(); + }); + + /** + * @tc.number GestureConflict_003 + * @tc.name GestureAndMotionControl + * @tc.desc 滑动页面. + */ + it('GestureAndMotionControl', 0, async (done: Function) => { + // 查找并点击第一个列表项 + const targetItem = await driver.findComponent(ON.text('Gesture and motion control')); + if (targetItem !== null) { + await targetItem.click(); + // 等待目标页面加载 + await driver.delayMs(10000); + + // 使用 swipe 方法向下滑动 + await driver.swipe(500, 1000, 500, 200, 100); + + // 返回首页 + await driver.pressBack(); + await driver.delayMs(1000); + } + done(); + }); + + /** + * @tc.number GestureConflict_004 + * @tc.name PreventGestureRecognition + * @tc.desc 长按页面,加速进度. + */ + it('PreventGestureRecognition', 0, async (done: Function) => { + try { + const targetItem = await driver.findComponent(ON.text('Preventing gesture participation in recognition')); + if (targetItem !== null) { + await targetItem.click(); + await driver.delayMs(3000); + const centerX = 500; + const centerY = 800; + await driver.swipe(centerX, centerY, centerX + 10, centerY + 10, 3000); + await driver.delayMs(3000); + await driver.pressBack(); + await driver.delayMs(1000); + } + done(); + } catch (error) { + hilog.error(DOMAIN, TAG,'error:', error); + done(error); + } + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..d5155f901adda0baec09cfff28c20e531db6e67f --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import abilityTest from './Ability.test'; +import index from './Index.test'; + + +export default function testsuite() { + abilityTest(); + index() +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/ohosTest/module.json5 b/ArkUIKit/GestureConflict/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1cafc28b86d7d9f2b34f24d26a75c0dbd7299715 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/ohosTest/module.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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/GestureConflict/entry/src/test/List.test.ets b/ArkUIKit/GestureConflict/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..a60c87c5cbb0badf7c3fd8975034590e6fafa992 --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/entry/src/test/LocalUnit.test.ets b/ArkUIKit/GestureConflict/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..841bfd77e56060e50ec0924302a5ae624e76e3aa --- /dev/null +++ b/ArkUIKit/GestureConflict/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/hvigor/hvigor-config.json5 b/ArkUIKit/GestureConflict/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/ArkUIKit/GestureConflict/hvigor/hvigor-config.json5 @@ -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. + */ +{ + "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/GestureConflict/hvigorfile.ts b/ArkUIKit/GestureConflict/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/ArkUIKit/GestureConflict/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/oh-package.json5 b/ArkUIKit/GestureConflict/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..837c0ff9f35a6bb9eea849fead7955c19bcdec8d --- /dev/null +++ b/ArkUIKit/GestureConflict/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "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/GestureConflict/ohosTest.md b/ArkUIKit/GestureConflict/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..618aae89f609eae8054c601492e9112f15f05c8d --- /dev/null +++ b/ArkUIKit/GestureConflict/ohosTest.md @@ -0,0 +1,6 @@ +| 测试功能 | 预置条件 | 输入 | 预期输出 | 测试结果 | +|----------| ------------ |---------------------------------|-------------------| -------- | +| 首页加载测试 | 设备正常运行 | 验证基础元素渲染 | 检查标题和列表组件 | Pass | +| 自定义手势判定 | 设备正常运行 | 点击'Custom gesture recognition' | 跳转成功且页面存在Image组件 | Pass | +| 手势并行动态控制 | 设备正常运行 | 点击'Gesture and motion control' | 跳转成功且包含嵌套滚动组件 | Pass | +| 阻止手势参与识别 | 设备正常运行 | 点击'Prevent Gesture Recognition' | 跳转成功且根据手势决定数字增加速度 | Pass | \ No newline at end of file diff --git a/ArkUIKit/GestureConflict/screenshots/GestureRecognition.png b/ArkUIKit/GestureConflict/screenshots/GestureRecognition.png new file mode 100644 index 0000000000000000000000000000000000000000..a0956d878dbe36f33be9b08ebcc71cdcefadbc4a Binary files /dev/null and b/ArkUIKit/GestureConflict/screenshots/GestureRecognition.png differ diff --git a/ArkUIKit/GestureConflict/screenshots/Home.jpg b/ArkUIKit/GestureConflict/screenshots/Home.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe8d0975bcdb09372aedae8ba288164fd0cbf412 Binary files /dev/null and b/ArkUIKit/GestureConflict/screenshots/Home.jpg differ diff --git a/ArkUIKit/GestureConflict/screenshots/Stop.jpg b/ArkUIKit/GestureConflict/screenshots/Stop.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ba56fe7d23a05f9a0f8ae9c0152c1b30bde58f46 Binary files /dev/null and b/ArkUIKit/GestureConflict/screenshots/Stop.jpg differ diff --git a/ArkUIKit/GestureConflict/screenshots/kineticControl.jpg b/ArkUIKit/GestureConflict/screenshots/kineticControl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..73e15599235b4d3cb98cefc2f9c39f207ed5fdd2 Binary files /dev/null and b/ArkUIKit/GestureConflict/screenshots/kineticControl.jpg differ diff --git a/ArkUIKit/GestureConflict/screenshots/userDefined.jpg b/ArkUIKit/GestureConflict/screenshots/userDefined.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfafefe386449a7e3ee1cf6c776809215ef8d086 Binary files /dev/null and b/ArkUIKit/GestureConflict/screenshots/userDefined.jpg differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/AppScope/app.json5 b/ArkUIKit/UIExtensionAndAccessibility/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..05b143854f1a6bbe4075b8b153b77f14ac0c605a --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.samples.uiextensionandaccessibility", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/AppScope/resources/base/element/string.json b/ArkUIKit/UIExtensionAndAccessibility/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..cf7e44a7137cc83ab2c56c263b3f53895aea2e72 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "UIExtensionAndAccessibility" + } + ] +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/AppScope/resources/base/media/app_icon.png b/ArkUIKit/UIExtensionAndAccessibility/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/AppScope/resources/base/media/app_icon.png differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/README_zh.md b/ArkUIKit/UIExtensionAndAccessibility/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..e984c42ae2fee8d7ebb9443dde3bed46576d69c5 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/README_zh.md @@ -0,0 +1,108 @@ +# 使用UIExtension控件与ArkUI无障碍指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解UIExtension控件与ArkUI无障碍属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [跨进程应用能力扩展(UIExtension,仅对系统应用开放)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-ui-extension-components.md)。 +2. [同应用进程嵌入式组件 (EmbeddedComponent)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-embedded-components.md)。 +3. [全屏启动原子化服务组件(FullScreenLaunchComponent)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-FullScreenComponent.md)。 +4. [跨线程嵌入式组件 (IsolatedComponent,仅对系统应用开放)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-isolated-components.md)。 +5. [支持无障碍](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-universal-attributes-accessibility.md)。 + +### 效果预览 + +| 首页选项目录 | Isolated目录 | Isolated示例 | Embedded示例 +|------------------------------------|------------------------------------|------------------------------------|--------------------------------------| +| ![](screenshots/device/image1.jpg) | ![](screenshots/device/image2.jpg) | ![](screenshots/device/image3.jpg) | ![](screenshots/device/Embedded.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +|---pages +| |---EmbeddedComponent // EmbeddedComponent 组件 +| | |---Embedded.ets +| | |---Extension.ets +| | |---Index.ets +| |---FullScreenLaunchComponent // FullScreenLaunchComponent 组件 +| | |---FullScreenLaunch.ets +| | |---Index.ets +| |---IsolatedComponent // IsolatedComponent 组件 +| | |---Extension.ets +| | |---Index.ets +| | |---Isolated.ets +| |---UIExtensionComponent // UIExtensionComponent 组件 +| | |---Extension.ets +| | |---Index.ets +| | |---UIExtension.ets +| |---UniversalAttributesAccessibility // ArkUI 无障碍能力 +| | |---AccessibilityFocusDrawLevel.ets +| | |---AccessibilityGroup.ets +| | |---AccessibilityText.ets +| | |---Index.ets +|---pages +| |---Index.ets // 应用主页面 +entry/src/ohosTest/ +|---ets +| |---index.test.ets // 示例代码测试代码 +``` + +### 具体实现 + +1. 引入必要头文件,包括日志、ArkUI 节点、元能力 Want 等接口定义。 +2. 定义错误和终止事件回调函数 onError、onTerminated,暂为空实现。 +3. 实现嵌入式组件创建函数 embeddedNode: +4. 获取 NAPI 回调参数,提取节点内容句柄。 +5. 获取 ArkUI 节点 API 接口,创建嵌入式组件节点。 +6. 构造元能力 Element,包含包名、能力名等信息,创建 Want 对象并设置为组件属性。 +7. 创建嵌入式组件选项,绑定事件回调并设置为组件属性。 +8. 设置组件宽高属性 +9. 创建Column容器,设置属性并将嵌入式组件作为字节点添加 +10. Column容器添加到节点内容 + +### 相关权限 + +允许系统方舟运行时引擎在受限模式下执行动态下发的方舟字节码。 + +[ohos.permission.RUN_DYN_CODE](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionrun_dyn_code) + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行, 支持设备:RK3568。 + +2.本示例为Stage模型,支持API20版本SDK,版本号:6.0.0.35,镜像版本号:OpenHarmony_6.0.0.35。 + +3.本示例需要使用DevEco Studio 5.0.3 Release (Build Version: 5.0.9.300, built on March 13, 2025)及以上版本才可编译运行。 + +4.本示例类型为系统应用,需要使用Full SDK,使用Full SDK时需要手动从镜像站点获取,并在DevEco Studio中替换,具体操作可参考[替换指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/faqs/full-sdk-switch-guide.md)。 + +5.本示例涉及相关权限为system_core级别(相关权限级别可通过[权限定义列表](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md)查看),需要手动配置对应级别的权限签名(具体操作可查看[应用包签名工具概述](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/hapsigntool-overview.md#%E5%BA%94%E7%94%A8%E5%8C%85%E7%AD%BE%E5%90%8D%E5%B7%A5%E5%85%B7%E6%A6%82%E8%BF%B0))。 + +6.本示例类型为系统应用,需要手动配置对应级别的应用类型("app-feature": "hos_system_app")。具体可参考profile配置文件[bundle-info对象内部结构](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/app-provision-structure.md#bundle-info%E5%AF%B9%E8%B1%A1%E5%86%85%E9%83%A8%E7%BB%93%E6%9E%84)。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/UIExtensionAndAccessibility > .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/UIExtensionAndAccessibility/build-profile.json5 b/ArkUIKit/UIExtensionAndAccessibility/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..65266701ad11d549856f645012a1442351b231e0 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "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 + } + } + } + ], + "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/UIExtensionAndAccessibility/code-linter.json5 b/ArkUIKit/UIExtensionAndAccessibility/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/build-profile.json5 b/ArkUIKit/UIExtensionAndAccessibility/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..eac65cd9afc8f5704686f199eac28e00f273bec6 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/build-profile.json5 @@ -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. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": ["arm64-v8a", "x86_64"] + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/hvigorfile.ts b/ArkUIKit/UIExtensionAndAccessibility/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e4f43d54667f8327c367c8096bd08bb8c75aff54 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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. */ +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/obfuscation-rules.txt b/ArkUIKit/UIExtensionAndAccessibility/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/oh-package.json5 b/ArkUIKit/UIExtensionAndAccessibility/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..451b0fa58fbfacac0d5dccbb67e47e3d141afdd2 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/oh-package.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. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} + diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/CMakeLists.txt b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e0ecbf4fcca5a3c26ed96a20d9a6445536b75201 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(entry) + +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 embedded/embedded.cpp embedded/embeddedInit.cpp) + +target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so libhilog_ndk.z.so libability_base_want.so) + diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/common/common.h b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/common/common.h new file mode 100644 index 0000000000000000000000000000000000000000..61d3e2a67499d19d8be8681b6d906240be489cc1 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/common/common.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVE_EMBEDDED_COMMON_H +#define NATIVE_EMBEDDED_COMMON_H +#define SIZE_300 300 +#define SIZE_401 401 + + +const unsigned int LOG_PRINT_DOMAIN = 0xFF00; + +#endif // NATIVE_EMBEDDED_COMMON_H diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embedded.cpp b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embedded.cpp new file mode 100644 index 0000000000000000000000000000000000000000..030f62d6826bed52704f59a1e0be84035256ab38 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embedded.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "arkui/native_node_napi.h" +#include "arkui/native_interface.h" +#include "common/common.h" +#include "napi/native_api.h" +#include "embedded.h" +//[Start embeddedComponentCTest_start] +#include +#include +#include //引用元能力want头文件 + +// 注册事件 +void onError(int32_t code, const char *name, const char *message) {} +void onTerminated(int32_t code, AbilityBase_Want *want) {} +//[StartExclude embeddedComponentCTest_start] +napi_value embeddedNode(napi_env env, napi_callback_info info) +{ + size_t argCnt = 1; + napi_value args[1] = {nullptr}; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginManager", "CreateNativeNode napi_get_cb_info failed"); + } + ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr; + ArkUI_NodeContentHandle nodeContentHandle = nullptr; + OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle); + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + // 创建节点 + ArkUI_NodeHandle embeddedNode = nodeAPI->createNode(ARKUI_NODE_EMBEDDED_COMPONENT); + //[EndExclude embeddedComponentCTest_start] + // 设置属性 + AbilityBase_Element Element = {.bundleName = "com.example.uiextensionandaccessibility", + .abilityName = "ExampleEmbeddedAbility", + .moduleName = "entry"}; // 由元能力提供接口 + AbilityBase_Want *want = OH_AbilityBase_CreateWant(Element); // 由元能力提供接口 + if (want == nullptr) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "AbilityBase_Want", "~PluginManager"); + } + ArkUI_AttributeItem itemobjwant = {.object = want}; + nodeAPI->setAttribute(embeddedNode, NODE_EMBEDDED_COMPONENT_WANT, &itemobjwant); + + auto embeddedNode_option = OH_ArkUI_EmbeddedComponentOption_Create(); + auto onErrorCallback = onError; + auto onTerminatedCallback = onTerminated; + OH_ArkUI_EmbeddedComponentOption_SetOnError(embeddedNode_option, onErrorCallback); + OH_ArkUI_EmbeddedComponentOption_SetOnTerminated(embeddedNode_option, onTerminatedCallback); + + ArkUI_AttributeItem itemobjembeddedNode = {.object = embeddedNode_option}; + nodeAPI->setAttribute(embeddedNode, NODE_EMBEDDED_COMPONENT_OPTION, &itemobjembeddedNode); + + // 设置基本属性,如宽高 + ArkUI_NumberValue value[] = {480}; + ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)}; + value[0].f32 = SIZE_300; + nodeAPI->setAttribute(embeddedNode, NODE_WIDTH, &item); + nodeAPI->setAttribute(embeddedNode, NODE_HEIGHT, &item); + + // 创建Column + ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN); + nodeAPI->setAttribute(column, NODE_WIDTH, &item); + ArkUI_NumberValue column_bc[] = {{.u32 = 0xFFF00BB}}; + ArkUI_AttributeItem column_item = {column_bc, 1}; + nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &column_item); + ArkUI_AttributeItem column_id = {.string = "Column_CAPI"}; + nodeAPI->setAttribute(column, NODE_ID, &column_id); + + // 上树 + nodeAPI->addChild(column, embeddedNode); + //[End embeddedComponentCTest_start] + int32_t result = OH_ArkUI_NodeContent_AddNode(nodeContentHandle, column); + napi_value retValue = 0; + napi_create_int32(env, result, &retValue); + if (result == SIZE_401) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "OH_ArkUI_NodeContent_AddNode_Result", "result"); + } + napi_value exports; + + if (napi_create_object(env, &exports) != napi_ok) { + napi_throw_type_error(env, NULL, "napi_create_object failed"); + return nullptr; + } + return exports; +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embedded.h b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embedded.h new file mode 100644 index 0000000000000000000000000000000000000000..e46a1d15791f82aeb41679db69c3ff9d7d695c19 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embedded.h @@ -0,0 +1,13 @@ +// +// Created on 2025/10/17. +// +// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, +// please include "napi/native_api.h". + +#ifndef UIEXTENSIONANDACCESSIBILITY_EMBEDDED_H +#define UIEXTENSIONANDACCESSIBILITY_EMBEDDED_H +#include "napi/native_api.h" + +napi_value embeddedNode(napi_env env, napi_callback_info info); + +#endif // UIEXTENSIONANDACCESSIBILITY_EMBEDDED_H diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embeddedInit.cpp b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embeddedInit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c5a0cb396d64abd813d09107b61d3348539690f --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/embedded/embeddedInit.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "common/common.h" +#include "embedded/embedded.h" +#include + +EXTERN_C_START +namespace nativeEmbedded { +static void RenderInitPush0(napi_property_descriptor *desc) +{ + napi_property_descriptor descTemp[] = { + {"embeddedNode", nullptr, embeddedNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + }; + for (size_t index = 0; index < sizeof(descTemp) / sizeof(descTemp[0]); index++) { + desc[index] = descTemp[index]; + } +} + +static napi_value RenderInit(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[10] = {}; + RenderInitPush0(desc); + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module embeddedModule = {.nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = nativeEmbedded::RenderInit, + .nm_modname = "entry", + .nm_priv = ((void *)0), + .reserved = {0}}; + +extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&embeddedModule); } +// namespace NativeXComponentSample +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/types/libentry/index.d.ts b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/types/libentry/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..3204a3eac3abde1ab48049cca7bcb601dc905931 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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. + */ + +import { Content } from "@kit.ArkUI"; + +export const embeddedNode: (Node: Content) => void; \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/types/libentry/oh-package.json5 b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..da3d1c3825df6ab56e2bf2821d988f1257f34795 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "libentry.so", + "types": "./index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/Card.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/Card.ets new file mode 100644 index 0000000000000000000000000000000000000000..608bc4912c7f033aaeb2332b290b1d0ea0b7cb82 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/Card.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. + */ + +@Component +export struct CompletedRoutableCard { + @Prop + symbol: Resource = $r('sys.symbol.label'); + @Prop + @Require + title: string; + @Prop + @Require + description: ResourceStr; + + build() { + Card({ verticalAlign: VerticalAlign.Top }) { + Button({ type: ButtonType.Circle }) { + SymbolGlyph(this.symbol) + .fontColor(['#fff']) + .fontSize(16) + } + .borderRadius(14) + + Column({ space: 8 }) { + Text(this.title) + .fontColor($r('sys.color.font_primary')) + + Text(this.description) + .fontColor($r('sys.color.font_secondary')) + .fontSize($r('sys.float.Body_S')) + } + .alignItems(HorizontalAlign.Start) + .layoutWeight(1) + } + } +} + +@Component +export struct Card { + @Prop + verticalAlign: VerticalAlign = VerticalAlign.Center; + @BuilderParam + content: () => void; + + build() { + Row({ space: 12 }) { + this.content() + } + .alignItems(this.verticalAlign) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + } +} + +@Component +export struct RoutableCard { + @Prop + icon: Resource = $r('sys.symbol.label'); + @Prop + @Require + title: ResourceStr; + + build() { + Card() { + Button({ type: ButtonType.Circle }) { + SymbolGlyph(this.icon) + .fontColor(['#fff']) + .fontSize(16) + } + .borderRadius(14) + + Text(this.title) + .fontColor($r('sys.color.font_primary')) + .minFontSize(12) + .maxFontSize(16) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + + Blank() + + Button({ type: ButtonType.Normal, buttonStyle: ButtonStyleMode.TEXTUAL }) { + SymbolGlyph($r('sys.symbol.chevron_right')) + .fontSize(18) + .fontColor([$r('sys.color.font_secondary')]) + } + } + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/Route.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/Route.ets new file mode 100644 index 0000000000000000000000000000000000000000..859fec8c9ebd491e575d5baf8d43bd0512add60c --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/Route.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Route { + title: string; + name: string; + items?: Route[]; + description?: ResourceStr; +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/resource.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/resource.ets new file mode 100644 index 0000000000000000000000000000000000000000..e240a1079ad09a0f19080b49b57a6a0720416e6c --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/common/resource.ets @@ -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. + */ + +export class ResourceManager { + public resourceToString(resource: Resource): string { + return getContext(this).resourceManager.getStringSync(resource); + } +} + +// 默认导出let +let resourceToStringManager = new ResourceManager(); + +export default resourceToStringManager as ResourceManager; \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..7bd9072c5090c332be2f707ecc88ce7c4d993b38 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/entryability/EntryAbility.ets @@ -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. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/main/ets/extensionability/ExampleEmbeddedAbility.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/extensionability/ExampleEmbeddedAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..66471442abf7dd9214dc5bc8aef067dcbfc9a8c0 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/extensionability/ExampleEmbeddedAbility.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. + */ +// [Start exampleEmbeddedAbility_start] +import { EmbeddedUIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit'; + +const TAG: string = '[ExampleEmbeddedAbility]' + +export default class ExampleEmbeddedAbility extends EmbeddedUIExtensionAbility { + onCreate() { + console.log(TAG, `onCreate`); + } + + onForeground() { + console.log(TAG, `onForeground`); + } + + onBackground() { + console.log(TAG, `onBackground`); + } + + onDestroy() { + console.log(TAG, `onDestroy`); + } + + onSessionCreate(want: Want, session: UIExtensionContentSession) { + console.log(TAG, `onSessionCreate, want: ${JSON.stringify(want)}`); + let param: Record = { + 'session': session + }; + let storage: LocalStorage = new LocalStorage(param); + // 加载 Extension.ets 页面内容 + session.loadContent('pages/EmbeddedComponent/Extension', storage); + } + + onSessionDestroy(session: UIExtensionContentSession) { + console.log(TAG, `onSessionDestroy`); + } +} +// [End exampleEmbeddedAbility_start] diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Embedded.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Embedded.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ae6cdf23be1beb22681f668a76dea14c7a5e138 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Embedded.ets @@ -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. + */ + +// [Start embedded_start] +import { Want } from '@kit.AbilityKit'; + +@Component +export struct Embedded { + @State message: string = 'Message: '; + private want: Want = { + bundleName: 'com.samples.uiextensionandaccessibility', + abilityName: 'ExampleEmbeddedAbility', + }; + build() { + NavDestination() { + Row() { + Column() { + Text(this.message).fontSize(30) + EmbeddedComponent(this.want, EmbeddedType.EMBEDDED_UI_EXTENSION) + .width('100%') + .height('90%') + .onTerminated((info) => { + // 点击extension页面内的terminateSelfWithResult按钮后触发onTerminated回调,文本框显示如下信息 + this.message = `Termination: code = ${info.code} , want = ${ JSON.stringify(info.want)}`; + }) + .onError((error) => { + // 失败或异常触发onError回调,文本框显示如下报错内容 + this.message = `Error: code = ${error.code}`; + }) + } + .width('100%') + } + .height('100%') + } + .backgroundColor('#f1f2f3') + // $r('app.media.Embedded_Component_title')需要替换为开发者所需的文本资源文件 + .title($r('app.string.Embedded_Component_title')) + } +} +// [End embedded_start] \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Extension.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Extension.ets new file mode 100644 index 0000000000000000000000000000000000000000..d487a0b41a1ac71b0e2251085762cb1d73bf7856 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Extension.ets @@ -0,0 +1,45 @@ +/* + * 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 extension_start] +import { UIExtensionContentSession } from '@kit.AbilityKit'; + +let storage = LocalStorage.getShared(); + +@Entry(storage) +@Component +struct Extension { + @State message: string = 'EmbeddedUIExtensionAbility Index'; + private session: UIExtensionContentSession | undefined = storage.get('session'); + + build() { + Column() { + Text(this.message) + .fontSize(20) + .fontWeight(FontWeight.Bold) + Button('terminateSelfWithResult').fontSize(20).onClick(() => { + // 点击按钮后调用terminateSelfWithResult退出 + this.session?.terminateSelfWithResult({ + resultCode: 1, + want: { + bundleName: 'com.samples.uiextensionandaccessibility', + abilityName: 'ExampleEmbeddedAbility', + } + }); + }) + }.width('100%').height('100%') + } +} +// [End extension_start] \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Index.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..0e203ba4af5e4b686f5f42dfcb93412bc7bbe2ce --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/EmbeddedComponent/Index.ets @@ -0,0 +1,70 @@ +/* + * 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 { CompletedRoutableCard } from '../../common/Card'; +import { Route } from '../../common/Route'; +import { Embedded } from './Embedded'; +import resource from '../../common/resource'; + +export const EMBEDDED_ROUTE_PREFIX: string = 'EmbeddedComponent'; + +const routes: Route[] = [ + { + name: `${EMBEDDED_ROUTE_PREFIX}/Embedded`, + // $r('app.media.Embedded_Component_title')需要替换为开发者所需的文本资源文件 + title: resource.resourceToString($r('app.string.Embedded_Component_title')), + // $r('app.media.Embedded_Component_description')需要替换为开发者所需的文本资源文件 + description: resource.resourceToString($r('app.string.Embedded_Component_description')), + } +] + +@Builder +export function EmbeddedDestination(name: string) { + if (name == EMBEDDED_ROUTE_PREFIX) { + EmbeddedExample(); + } else if (name == routes[0].name) { + Embedded(); + } +} + +@Entry +@Component +struct EmbeddedExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + // $r('app.media.pageIndex_EmbeddedComponent')需要替换为开发者所需的文本资源文件 + .title(resource.resourceToString($r('app.string.pageIndex_EmbeddedComponent')), { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/FullScreenLaunchComponent/FullScreenLaunch.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/FullScreenLaunchComponent/FullScreenLaunch.ets new file mode 100644 index 0000000000000000000000000000000000000000..b4412c5c440bcb03b1177e7978fe9a09b1ac30dc --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/FullScreenLaunchComponent/FullScreenLaunch.ets @@ -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. + */ + +import { FullScreenLaunchComponent } from '@kit.ArkUI' + +@Builder +function sampleColumnChild() { + Column() { + Image($r('app.media.app_icon')) + Text('test') + } +} + +@Component +export struct FullScreenLaunch { + @State appId: string = '5765880207855083101'; // 原子化服务appId + + build() { + NavDestination() { + Column() { + FullScreenLaunchComponent({ + content: sampleColumnChild, + appId: this.appId, + options: {}, + onTerminated: (info) => { + console.info('onTerminated code: ' + info.code.toString()); + }, + onError: (err) => { + console.error('onError code: ' + err.code + ', message: ', err.message); + } + }).width('80vp').height('80vp') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Full_Screen_Launch_Component_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/FullScreenLaunchComponent/Index.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/FullScreenLaunchComponent/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..5d3e4520ac0657c95438f443e5e593c6c8d29b4d --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/FullScreenLaunchComponent/Index.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 { CompletedRoutableCard } from '../../common/Card' +import { Route } from '../../common/Route' +import { FullScreenLaunch } from './FullScreenLaunch' +import resource from '../../common/resource' + +export const SCREEN_ROUTE_PREFIX: string = 'FullScreenLaunchComponent'; + +const routes: Route[] = [ + { + name: `${SCREEN_ROUTE_PREFIX}/FullScreenLaunch`, + title: resource.resourceToString($r('app.string.Full_Screen_Launch_Component_title')), + description: resource.resourceToString($r('app.string.Full_Screen_Launch_Component_description')), + } +]; + +@Builder +export function FullScreenDestination(name: string) { + if (name == SCREEN_ROUTE_PREFIX) { + FullScreenExample(); + } else if (name == routes [0].name) { + FullScreenLaunch(); + } +} + +@Entry +@Component +struct FullScreenExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title(resource.resourceToString($r('app.string.pageIndex_FullScreenLaunchComponent')), { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/Index.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..e1e905490fb8c4e6d4007a794404cd850345e2cd --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,133 @@ +/* + * 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 { LengthMetrics } from '@kit.ArkUI'; +import { RoutableCard } from '../common/Card'; +import { Route } from '../common/Route'; +import resource from '../common/resource'; +import { UI_EXTENSION_ROUTE_PREFIX, UIExtensionDestination } from './UIExtensionComponent/Index'; +import { EMBEDDED_ROUTE_PREFIX, EmbeddedDestination } from './EmbeddedComponent/Index'; +import { SCREEN_ROUTE_PREFIX, FullScreenDestination } from './FullScreenLaunchComponent/Index'; +import { ISOLATED_ROUTE_PREFIX, IsolatedDestination } from './IsolatedComponent/Index'; +import { ACCESSIBILITY_ROUTE_PREFIX, AccessibilityDestination } from './UniversalAttributesAccessibility/Index'; +import { UIContext } from '@kit.ArkUI'; + +const routes: Route[] = [ + { + title: resource.resourceToString($r('app.string.pageIndex_UIExtensionComponent')), + name: UI_EXTENSION_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_EmbeddedComponent')), + name: EMBEDDED_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_FullScreenLaunchComponent')), + name: SCREEN_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_IsolatedComponent')), + name: ISOLATED_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_UniversalAttributesAccessibility')), + name: ACCESSIBILITY_ROUTE_PREFIX + } + +] + +@Builder +function Destination(name: string) { + if (name.startsWith(UI_EXTENSION_ROUTE_PREFIX)) { + UIExtensionDestination(name); + } else if (name.startsWith(EMBEDDED_ROUTE_PREFIX)) { + EmbeddedDestination(name); + } else if (name.startsWith(SCREEN_ROUTE_PREFIX)) { + FullScreenDestination(name); + } else if (name.startsWith(ISOLATED_ROUTE_PREFIX)) { + IsolatedDestination(name); + } else if (name.startsWith(ACCESSIBILITY_ROUTE_PREFIX)) { + AccessibilityDestination(name); + } +} + +@Entry +@Component +struct Index { + @State condition: string = ''; + @Provide pathStack: NavPathStack = new NavPathStack(); + + getFilteredRoutes(): Route[] { + if (!this.condition) { + return routes; + } + return routes.filter((route: Route) => { + return route.title.includes(this.condition); + }) + } + + @LocalBuilder + Title() { + Column() { + Search({ value: this.condition }) + .onChange(value => { + this.condition = value; + }) + .margin({ start: LengthMetrics.vp(16), end: LengthMetrics.vp(16) }) + } + .justifyContent(FlexAlign.Center) + .height('100%') + } + + build() { + Column(){ + Column(){ + Navigation(this.pathStack) { + List({ space: 12 }) { + ForEach(this.getFilteredRoutes(), (route: Route) => { + ListItem() { + RoutableCard({ title: route.title }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .padding({ start: LengthMetrics.vp(16), end: LengthMetrics.vp(16) }) + .contentStartOffset(56) + .height('100%') + .width('100%') + } + .backgroundColor('#f1f3f5') + .title({ builder: this.Title, height: 56 }, { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .navDestination(Destination) + .height('80%') + } + Button('showPage') + .onClick(()=>{ + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.pushUrl({ + url:'pages/ShowEmbeddedComponent/ShowPage' + }) + }) + } + .height('100%') + } +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Extension.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Extension.ets new file mode 100644 index 0000000000000000000000000000000000000000..ee7a575f273e723d96f73d4dd044f43516fdbfec --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Extension.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Entry +@Component +struct Extension { + @State message: string = 'Hello World'; + + build() { + RelativeContainer() { + Text(this.message) + .id('HelloWorld') + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Index.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..ed692a5febc0dc55700b97ef020f0e8129329c43 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Index.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 { CompletedRoutableCard } from '../../common/Card' +import { Route } from '../../common/Route' +import { Isolated } from './Isolated' +import resource from '../../common/resource' + +export const ISOLATED_ROUTE_PREFIX: string = 'IsolatedComponent'; + +const routes: Route[] = [ + { + name: `${ISOLATED_ROUTE_PREFIX}/Isolated`, + title: resource.resourceToString($r('app.string.Isolated_Component_title')), + description: resource.resourceToString($r('app.string.Isolated_Component_description')), + } +]; + +@Builder +export function IsolatedDestination(name: string) { + if (name == ISOLATED_ROUTE_PREFIX) { + IsolatedExample(); + } else if (name == routes[0].name) { + Isolated(); + } +} + +@Entry +@Component +struct IsolatedExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title(resource.resourceToString($r('app.string.pageIndex_IsolatedComponent')), { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Isolated.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Isolated.ets new file mode 100644 index 0000000000000000000000000000000000000000..be205c089d6f7a149d6a8f4d7d117d5cfb9a2f82 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/IsolatedComponent/Isolated.ets @@ -0,0 +1,100 @@ +/* + * 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 { worker } from '@kit.ArkTS'; +import { bundleManager } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; + +// 对abc文件进行校验,并拷贝到指定沙箱路径下 +function sampleVerifyAbc(abcPaths: Array, deleteOriginalFiles: boolean) { + try { + bundleManager.verifyAbc(abcPaths, deleteOriginalFiles, (err) => { + if (err) { + console.error('VerifyAbc failed, error message: ' + err.message); + } else { + console.info('VerifyAbc successfully.'); + } + }); + } catch (err) { + let message = (err as BusinessError).message; + console.error('VerifyAbc failed, error message: ' + message); + } +} + +@Component +export struct Isolated { + @State isShow: boolean = false; + @State resourcePath: string = ''; + @State abcPath: string = ''; + @State entryPoint: string = ''; + // abc文件名 + private fileName: string = 'modules'; + // abc文件所属应用的bundleName + private bundleName: string = 'com.samples.uiextensionandaccessibility'; + // 受限worker + private worker ?: worker.RestrictedWorker = new worker.RestrictedWorker('entry/ets/workers/OhCardWorker.ets'); + + build() { + NavDestination() { + Row() { + Column({ space: 20 }) { + // 1.调用verifyAbc接口校验abc文件 + Button('verifyAbc').onClick(() => { + let abcFilePath = `${getContext(this).filesDir}/${this.fileName}.abc`; + console.log('abcFilePath: ' + abcFilePath); + sampleVerifyAbc([abcFilePath], false); + }).height(100).width(200) + + // 2.显示IsolatedComponent + Button('showIsolatedComponent').onClick(() => { + if (!this.isShow) { + // 资源路径 + this.resourcePath = `${getContext(this).filesDir}/${this.fileName}.hap`; + // abc文件校验后的沙箱路径 + this.abcPath = `/abcs${getContext(this).filesDir}/${this.fileName}`; + // 需要显示页面的入口路径 + this.entryPoint = `${this.bundleName}/entry/ets/pages/IsolatedComponent/Extension`; + this.isShow = true; + } + }).height(100).width(200) + + if (this.isShow) { + IsolatedComponent({ + want: { + 'parameters': { + 'resourcePath': this.resourcePath, + 'abcPath': this.abcPath, + 'entryPoint': this.entryPoint + } + }, + worker: this.worker + }) + .width(300) + .height(300) + .onError((err) => { + console.info('onError : ' + JSON.stringify(err)); + }) + } + } + .width('100%') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Isolated_Component_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/ShowEmbeddedComponent/ShowPage.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/ShowEmbeddedComponent/ShowPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..7a16ee61beeaab837351753d148b455594be8083 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/ShowEmbeddedComponent/ShowPage.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 render from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; +import { UIContext } from '@kit.ArkUI'; + +@Entry +@Component +export struct ShowPage { + private nodeContent: NodeContent = new NodeContent(); + onPageShow(): void { + render.embeddedNode(this.nodeContent); + } + build() { + Column({ space: 16 }) { + Button('back') + .onClick(()=>{ + const uiContext: UIContext = this.getUIContext(); + const router = uiContext.getRouter(); + router.back(); + }) + Text('ShowPage content') + .fontSize(20) + .fontWeight(FontWeight.Bold) + Column() { + ContentSlot(this.nodeContent) + } + .layoutWeight(1) + .width('100%') + } + .width('100%') + .height('100%') + .padding(16) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/Extension.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/Extension.ets new file mode 100644 index 0000000000000000000000000000000000000000..a117e2dbee1f660585d84a5f3e91605a23612bc1 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/Extension.ets @@ -0,0 +1,116 @@ +/* + * 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 { UIExtensionContentSession } from '@kit.AbilityKit'; + +let storage = LocalStorage.getShared() +AppStorage.setOrCreate('message', 'UIExtensionAbility') + +@Entry(storage) +@Component +struct Extension { + @StorageLink('message') storageLink: string = ''; + private session: UIExtensionContentSession | undefined = storage.get('session'); + pathStack: NavPathStack = new NavPathStack() + + @Builder + PageMap(name: string) { + if (name === 'hello') { + pageOneTmp() + } + } + + onPageShow() { + if (this.session != undefined) { + this.session.setReceiveDataCallback((data)=> { + this.storageLink = JSON.stringify(data) + console.info('invoke for test, handle callback set by setReceiveDataCallback successfully'); + }) + + this.session.setReceiveDataForResultCallback(func1) + } + } + + build() { + Navigation(this.pathStack) { + Row() { + Column() { + Text(this.storageLink) + .fontSize(20) + .fontWeight(FontWeight.Bold) + Button($r('app.string.UIExtensionComponent_button1')).onClick(()=>{ + if (this.session != undefined) { + this.session.sendData({'data': 543321}) + console.info('send 543321, for test') + } + }) + Button('terminate').onClick(()=> { + if (this.session != undefined) { + this.session.terminateSelf(); + } + storage.clear() + }) + Button('terminate with result').onClick(()=>{ + if (this.session != undefined) { + this.session.terminateSelfWithResult({ + resultCode: 0, + want: { + bundleName: 'myBundleName', + parameters: { 'result': 123456 } + } + }) + } + storage.clear() + }) + + Button($r('app.string.UIExtensionComponent_button2')).onClick(()=> { + this.pathStack.pushPath({ name: 'hello'}) + }) + } + } + .height('100%') + }.navDestination(this.PageMap) + .mode(NavigationMode.Stack) + } +} + +// pageOne +@Component +export struct pageOneTmp { + pathStack: NavPathStack = new NavPathStack() + + build() { + NavDestination() { + Column() { + Text('Hello World') + }.width('100%').height('100%') + }.title('pageOne') + .onBackPressed(() => { + const popDestinationInfo = this.pathStack.pop() + console.log('pop' + $r('app.string.UIExtensionComponent_return') + JSON.stringify(popDestinationInfo)) + return true + }) + .onReady((context: NavDestinationContext) => { + this.pathStack = context.pathStack + }) + } +} + +function func1(data: Record): Record { + let linkToMsg: SubscribedAbstractProperty = AppStorage.link('message'); + linkToMsg.set(JSON.stringify(data)) + console.info('invoke for test, handle callback set by setReceiveDataForResultCallback successfully'); + return data; +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/Index.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..da94cbb7279941b44457fe41af659e1ea9e4166c --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/Index.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 { CompletedRoutableCard } from '../../common/Card' +import { Route } from '../../common/Route' +import { UIExtension } from './UIExtension' +import resource from '../../common/resource' + +export const UI_EXTENSION_ROUTE_PREFIX: string = 'UIExtensionComponent'; + +const routes: Route[] = [ + { + name: `${UI_EXTENSION_ROUTE_PREFIX}/UIExtension`, + title: resource.resourceToString($r('app.string.UI_Extension_Component_title')), + description: resource.resourceToString($r('app.string.UI_Extension_Component_description')), + } +]; + +@Builder +export function UIExtensionDestination(name: string) { + if (name == UI_EXTENSION_ROUTE_PREFIX) { + UIExtensionExample(); + } else if (name == routes[0].name) { + UIExtension(); + } +} + +@Entry +@Component +struct UIExtensionExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title(resource.resourceToString($r('app.string.pageIndex_UIExtensionComponent')), { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/UIExtension.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/UIExtension.ets new file mode 100644 index 0000000000000000000000000000000000000000..47b27931ad69a11ed6366072ea84a262194237b9 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UIExtensionComponent/UIExtension.ets @@ -0,0 +1,120 @@ +/* + * 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 { ComponentContent } from '@kit.ArkUI' + +class Params { +} + +@Builder +function sampleLoadingBuilder(params: Params) { + Column() { + LoadingProgress() + .color(Color.Blue) + } +} + +@Builder +function sampleAreaChangePlaceholderBuilder(params: Params) { + Column() { + } + .width('100%') + .height('100%') + .backgroundColor(Color.Orange) +} + +@Component +export struct UIExtension { + @State message1: string = 'Hello World 1' + @State message2: string = 'Hello World 2' + @State message3: string = 'Hello World 3' + @State visible: Visibility = Visibility.Hidden + @State wid: number = 300 + @State hei: number = 300 + private proxy: UIExtensionProxy | null = null; + private initPlaceholder = new ComponentContent(this.getUIContext(), wrapBuilder(sampleLoadingBuilder), new Params); + private areaChangePlaceholder = + new ComponentContent(this.getUIContext(), wrapBuilder(sampleAreaChangePlaceholderBuilder), new Params); + + build() { + NavDestination() { + Column() { + Column() { + Text(this.message1).fontSize(25) + Text(this.message2).fontSize(25) + Text(this.message3).fontSize(25) + + UIExtensionComponent({ + bundleName: 'com.samples.uiextensionandaccessibility', + abilityName: 'UIExtensionProvider', + parameters: { + 'ability.want.params.uiExtensionType': 'sys/commonUI' + }}, + { + placeholder: this.initPlaceholder, + areaChangePlaceholder: { + 'FOLD:TO:EXPAND': this.areaChangePlaceholder, + } + }) + .width(this.wid) + .height(this.hei) + .border({ width: 5, color: Color.Blue }) + .onReceive((data) => { + console.info('Lee onReceive, for test') + this.message3 = JSON.stringify(data['data']) + }) + .onTerminated((info) => { + console.info('onTerminated: code =' + info.code + ', want = ' + JSON.stringify(info.want)); + }) + .onError((error) => { + console.info('TestUEC onError, code: ' + error.code.toString() + ', message: ' + error.message); + }) + .onRemoteReady((proxy) => { + console.info('onRemoteReady, for test') + this.proxy = proxy + this.proxy.on('asyncReceiverRegister', syncRegisterCallback1); + this.proxy.on('asyncReceiverRegister', (proxy1) => { + console.info('on invoke for test, type is asyncReceiverRegister') + }); + }) + Button($r('app.string.UIExtensionComponent_button3')).onClick(() => { + if (this.proxy != undefined) { + this.proxy.send({ data: $r('app.string.UIExtensionComponent_hello1') }) + try { + let re = this.proxy.sendSync({ data: $r('app.string.UIExtensionComponent_hello2') }); + console.info('for test, re = ' + JSON.stringify(re)); + } catch (err) { + console.error(`sendSync failed for test. errCode = ${err.code}, message = ${err.message}`); + } + } + }) + } + } + .height('100%') + .width('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.UI_Extension_Component_title')) + } +} + +function syncRegisterCallback1(proxy: UIExtensionProxy) { + console.info('on invoke for test, syncRegisterCallback1, type is syncReceiverRegister') +} + +function syncRegisterCallback2(proxy: UIExtensionProxy) { + console.info('on invoke for test, syncRegisterCallback2, type is syncReceiverRegister') +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityFocusDrawLevel.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityFocusDrawLevel.ets new file mode 100644 index 0000000000000000000000000000000000000000..0fb40fb43ee987ea899c6392fe03465b851f6907 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityFocusDrawLevel.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. + */ + +import { ComponentContent } from '@kit.ArkUI'; + +class Params { +} + +@Builder +function loadingBuilder(params: Params) { + Column() { + LoadingProgress() + .color(Color.Blue) + } +} + +@Component +export struct AccessibilityFocusDrawLevel { + private contentNode = new ComponentContent(this.getUIContext(), wrapBuilder(loadingBuilder), new Params); + + build() { + NavDestination() { + Row() { + List() { + ListItem() { + Column() { + Stack() { + Column() { + Text($r('app.string.UniversalAttributesAccessibility_text5')) + Text($r('app.string.UniversalAttributesAccessibility_text5')) + .accessibilityFocusDrawLevel(FocusDrawLevel.TOP) + } + + Column() { + Text($r('app.string.UniversalAttributesAccessibility_text6')) + .backgroundColor(Color.Gray) + Text($r('app.string.UniversalAttributesAccessibility_text6')) + .backgroundColor(Color.Gray) + } + } + + Column() { + Text($r('app.string.UniversalAttributesAccessibility_text9')) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Column() { + UIExtensionComponent({ + bundleName: 'com.example.provide', + abilityName: 'EmptyUIExtensionAbility', + parameters: { + 'ability.want.params.uiExtensionType': 'sys/commonUI' + } + }, + { + placeholder: this.contentNode, + dpiFollowStrategy: DpiFollowStrategy.FOLLOW_UI_EXTENSION_ABILITY_DPI + }) + .onReceive((err) => { + console.error('onReceive' + JSON.stringify(err)); + }) + .onError((err) => { + console.error('onError code :' + err.code + ', name: ' + err.name + ', msg: ' + err.message); + console.error('onError' + JSON.stringify(err)); + }) + .accessibilityUseSamePage(AccessibilitySamePageMode.FULL_SILENT) + .width('50%') + .height('50%') + .backgroundColor(Color.Pink) + } + } + .width('100%') + .height('100%') + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text7')) + .accessibilityDescription($r('app.string.UniversalAttributesAccessibility_text8')) + + Column() { + Text($r('app.string.UniversalAttributesAccessibility_text10')) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + } + } + }.accessibilityScrollTriggerable(false) + } + .height('100%') + } + .backgroundColor('#f1f2f3') + .title($r('app.string.UniversalAttributesAccessibility_title3')) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityGroup.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityGroup.ets new file mode 100644 index 0000000000000000000000000000000000000000..86d6026b4084882c1ed8f05ad04092de7aec0eb9 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityGroup.ets @@ -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. + */ + +@Component +export struct AccessibilityGroup { + build() { + NavDestination() { + Column({ space: 10 }) { + Text('123456') + .focusable(true) + .borderRadius(5) + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text1')) + .accessibilityLevel('yes') + Button().accessibilityLevel('yes').accessibilityText($r('app.string.UniversalAttributesAccessibility_text2')) + Button($r('app.string.UniversalAttributesAccessibility_text3')).accessibilityLevel('yes') + Button() + Button('btn123').accessibilityText($r('app.string.UniversalAttributesAccessibility_text4')).accessibilityLevel('yes') + Button('btn123').accessibilityLevel('yes') + } + .accessibilityGroup(true, { accessibilityPreferred: true }) + .borderWidth(5) + .width('100%') + .height('100%') + } + .backgroundColor('#f1f2f3') + .title($r('app.string.UniversalAttributesAccessibility_title2')) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityText.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityText.ets new file mode 100644 index 0000000000000000000000000000000000000000..18f6bf9856793294a00a6ec3b74a52d4d18dd21a --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/AccessibilityText.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. + */ + +// [Start accessibility_text_start] +@Component +export struct AccessibilityText { + + @Builder customAccessibilityNode() { + Column() { + Text(`virtual node`) + } + .width(10) + .height(10) + } + + build() { + NavDestination() { + Row() { + // [StartExclude accessibility_text_start] + // [Start accessibility_group_start] + Column() { + Text('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold) + } + .accessibilityGroup(true) + // [End accessibility_group_start] + // [Start accessibility_level_start] + Column() { + Text('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold) + } + .accessibilityGroup(true) + .accessibilityLevel('yes') + // [End accessibility_level_start] + // [Start accessibility_text_group_start] + Column() { + Text('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold) + } + .accessibilityGroup(true) + .accessibilityLevel('yes') + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text7')) + // [End accessibility_text_group_start] + // [Start accessibility_description_start] + Column() { + Text('HelloWorld') + } + .accessibilityGroup(true) + .accessibilityLevel('yes') + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text7')) + .accessibilityDescription($r('app.string.UniversalAttributesAccessibility_text8')) + // [End accessibility_description_start] + // [Start accessibility_checked_start] + Column() { + Text('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold) + } + .accessibilityGroup(true) + .accessibilityLevel('yes') + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text7')) + .accessibilityDescription($r('app.string.UniversalAttributesAccessibility_text8')) + .accessibilityChecked(true) + // [End accessibility_checked_start] + // [Start accessibility_selected_start] + Column() { + Text('HelloWorld').fontSize(50).fontWeight(FontWeight.Bold) + } + .accessibilityGroup(true) + .accessibilityLevel('yes') + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text7')) + .accessibilityDescription($r('app.string.UniversalAttributesAccessibility_text8')) + .accessibilitySelected(undefined) + // [End accessibility_selected_start] + // [EndExclude accessibility_text_start] + Column() { + // $r('app.media.UniversalAttributesAccessibility_text5')需要替换为开发者所需的文本资源文件 + Text($r('app.string.UniversalAttributesAccessibility_text5')) + .fontSize(50) + .fontWeight(FontWeight.Bold) + // $r('app.media.UniversalAttributesAccessibility_text6')需要替换为开发者所需的文本资源文件 + Text($r('app.string.UniversalAttributesAccessibility_text6')) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + .accessibilityGroup(true) + .accessibilityLevel('yes') + // $r('app.media.UniversalAttributesAccessibility_text7')需要替换为开发者所需的文本资源文件 + .accessibilityText($r('app.string.UniversalAttributesAccessibility_text7')) + // $r('app.media.UniversalAttributesAccessibility_text8')需要替换为开发者所需的文本资源文件 + .accessibilityDescription($r('app.string.UniversalAttributesAccessibility_text8')) + .accessibilityVirtualNode(this.customAccessibilityNode) + .accessibilityChecked(true) + .accessibilitySelected(undefined) + } + .height('100%') + } + .backgroundColor('#f1f2f3') + // $r('app.media.UniversalAttributesAccessibility_title1')需要替换为开发者所需的文本资源文件 + .title($r('app.string.UniversalAttributesAccessibility_title1')) + } +} +// [End accessibility_text_start] \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/Index.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..f09015806b7674f82c4ce3cc40831766430977d7 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/Index.ets @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CompletedRoutableCard } from '../../common/Card' +import { Route } from '../../common/Route' +import { AccessibilityText } from './AccessibilityText' +import { AccessibilityGroup } from './AccessibilityGroup' +import { AccessibilityFocusDrawLevel } from './AccessibilityFocusDrawLevel' +import resource from '../../common/resource' +import { router } from '@kit.ArkUI' + +export const ACCESSIBILITY_ROUTE_PREFIX: string = 'UniversalAttributesAccessibility'; + +const routes: Route[] = [ + { + name: `${ACCESSIBILITY_ROUTE_PREFIX}/AccessibilityText`, + title: resource.resourceToString($r('app.string.UniversalAttributesAccessibility_title1')), + description: resource.resourceToString($r('app.string.UniversalAttributesAccessibility_description1')), + }, + { + name: `${ACCESSIBILITY_ROUTE_PREFIX}/AccessibilityGroup`, + title: resource.resourceToString($r('app.string.UniversalAttributesAccessibility_title2')), + description: resource.resourceToString($r('app.string.UniversalAttributesAccessibility_description2')), + }, + { + name: `${ACCESSIBILITY_ROUTE_PREFIX}/AccessibilityFocusDrawLevel`, + title: resource.resourceToString($r('app.string.UniversalAttributesAccessibility_title3')), + description: resource.resourceToString($r('app.string.UniversalAttributesAccessibility_description3')), + } +]; + +@Builder +export function AccessibilityDestination(name: string) { + if (name == ACCESSIBILITY_ROUTE_PREFIX) { + AccessibilityExample(); + } else if (name == routes[0].name) { + AccessibilityText(); + } else if (name == routes[1].name) { + AccessibilityGroup(); + } else if (name == routes[2].name) { + AccessibilityFocusDrawLevel(); + } +} + +@Entry +@Component +struct AccessibilityExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title(resource.resourceToString($r('app.string.pageIndex_UniversalAttributesAccessibility')), { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/VirtualNodeExample.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/VirtualNodeExample.ets new file mode 100644 index 0000000000000000000000000000000000000000..b18faadce25166899c12859c19eb13b19344e733 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/pages/UniversalAttributesAccessibility/VirtualNodeExample.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. + */ + +//[Start virtual_node_example_start] +@Entry +@Component +struct VirtualNodeExample { + @Builder customAccessibilityNode() { + Text($r('app.string.UniversalAttributesAccessibility_text6')) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + build() { + Column() { + Text($r('app.string.UniversalAttributesAccessibility_text5')) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .accessibilityGroup(true) + .accessibilityLevel('yes') + .accessibilityVirtualNode(this.customAccessibilityNode) + } +} +//[End virtual_node_example_start] + diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/uiextensionability/UIExtensionProvider.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/uiextensionability/UIExtensionProvider.ets new file mode 100644 index 0000000000000000000000000000000000000000..3d4be9beefdbe72f77f2cdc0026a8317a62f074b --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/uiextensionability/UIExtensionProvider.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. + */ + +// [Start uiExtensionProvider_start] +import { UIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit'; + +const TAG: string = '[UIExtAbility]' +export default class UIExtAbility extends UIExtensionAbility { + + onCreate() { + console.log(TAG, `UIExtAbility onCreate`) + } + + onForeground() { + console.log(TAG, `UIExtAbility onForeground`) + } + + onBackground() { + console.log(TAG, `UIExtAbility onBackground`) + } + + onDestroy() { + console.log(TAG, `UIExtAbility onDestroy`) + } + + onSessionCreate(want: Want, session: UIExtensionContentSession) { + console.log(TAG, `UIExtAbility onSessionCreate, want: ${JSON.stringify(want)}`) + let param: Record = { + 'session': session + }; + let storage: LocalStorage = new LocalStorage(param); + session.loadContent('pages/UIExtensionComponent/Extension', storage); + } + + onSessionDestroy(session: UIExtensionContentSession) { + console.log(TAG, `UIExtAbility onSessionDestroy`) + } +} +// [End uiExtensionProvider_start] \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/workers/OhCardWorker.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/workers/OhCardWorker.ets new file mode 100644 index 0000000000000000000000000000000000000000..e7ee86db8e5443c896cd70a484c94c065352cc9e --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/ets/workers/OhCardWorker.ets @@ -0,0 +1,45 @@ +/* + * 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 { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS'; + +const workerPort: ThreadWorkerGlobalScope = worker.workerPort; + +/** + * Defines the event handler to be called when the worker thread receives a message sent by the host thread. + * The event handler is executed in the worker thread. + * + * @param event message data + */ +workerPort.onmessage = (event: MessageEvents) => { +}; + +/** + * Defines the event handler to be called when the worker receives a message that cannot be deserialized. + * The event handler is executed in the worker thread. + * + * @param event message data + */ +workerPort.onmessageerror = (event: MessageEvents) => { +}; + +/** + * Defines the event handler to be called when an exception occurs during worker execution. + * The event handler is executed in the worker thread. + * + * @param event error message + */ +workerPort.onerror = (event: ErrorEvent) => { +}; \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/module.json5 b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c93d734a79dfff75a063a74d6a0063c6507db0e6 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/module.json5 @@ -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. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "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:app_name", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + }, + { + "name": "ExampleEmbeddedAbility", + "srcEntry": "./ets/extensionability/ExampleEmbeddedAbility.ets", + "type": "embeddedUI" + }, + { + "name": "UIExtensionProvider", + "srcEntry": "./ets/uiextensionability/UIExtensionProvider.ets", + "description": "1", + "label": "$string:app_name", + "type": "sys/commonUI", + "exported": true, + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.RUN_DYN_CODE", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "inuse" + } + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/element/color.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/main/resources/base/element/float.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/main/resources/base/element/string.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..032144ae44d78e250a8366a423da641c2f9e6516 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/element/string.json @@ -0,0 +1,164 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "UIExtensionProvider_desc", + "value": "description" + }, + { + "name": "UIExtensionProvider_label", + "value": "label" + }, + { + "name": "pageIndex_UIExtensionComponent", + "value": "UIExtensionComponent 组件" + }, + { + "name": "pageIndex_EmbeddedComponent", + "value": "EmbeddedComponent 组件" + }, + { + "name": "pageIndex_FullScreenLaunchComponent", + "value": "FullScreenLaunchComponent 组件" + }, + { + "name": "pageIndex_IsolatedComponent", + "value": "IsolatedComponent 组件" + }, + { + "name": "pageIndex_UniversalAttributesAccessibility", + "value": "ArkUI 无障碍能力" + }, + { + "name": "Embedded_Component_title", + "value": "使用 EmbeddedComponent 组件" + }, + { + "name": "Full_Screen_Launch_Component_title", + "value": "使用 FullScreenLaunch 组件" + }, + { + "name": "UI_Extension_Component_title", + "value": "使用 UIExtensionComponent 组件" + }, + { + "name": "Isolated_Component_title", + "value": "使用 IsolatedComponent 组件" + }, + { + "name": "UniversalAttributesAccessibility_title1", + "value": "使用无障碍属性 1" + }, + { + "name": "UniversalAttributesAccessibility_title2", + "value": "使用无障碍属性 2" + }, + { + "name": "UniversalAttributesAccessibility_title3", + "value": "使用无障碍属性 3" + }, + { + "name": "Embedded_Component_description", + "value": "展示 EmbeddedComponent 组件的基础使用方式" + }, + { + "name": "Full_Screen_Launch_Component_description", + "value": "展示 FullScreenLaunch 组件的基础使用方式" + }, + { + "name": "UI_Extension_Component_description", + "value": "加载UIExtension" + }, + { + "name": "Isolated_Component_description", + "value": "展示 IsolatedComponent 组件的基础使用方式" + }, + { + "name": "UniversalAttributesAccessibility_description1", + "value": "设置无障碍文本和无障碍说明" + }, + { + "name": "UniversalAttributesAccessibility_description2", + "value": "设置无障碍组" + }, + { + "name": "UniversalAttributesAccessibility_description3", + "value": "设置无障碍焦点绿框绘制层级" + }, + { + "name": "UIExtensionComponent_button1", + "value": "点击向Component发送数据" + }, + { + "name": "UIExtensionComponent_button2", + "value": "点击跳转" + }, + { + "name": "UIExtensionComponent_button3", + "value": "点击向UIExtensionAbility发送数据" + }, + { + "name": "UIExtensionComponent_return", + "value": "点击跳转" + }, + { + "name": "UIExtensionComponent_hello1", + "value": "你好1" + }, + { + "name": "UIExtensionComponent_hello2", + "value": "你好2" + }, + { + "name": "UniversalAttributesAccessibility_text1", + "value": "有accessibility有text优先读accessibility" + }, + { + "name": "UniversalAttributesAccessibility_text2", + "value": "accessibility无text 读accessibility" + }, + { + "name": "UniversalAttributesAccessibility_text3", + "value": "无accessibility有text 读text" + }, + { + "name": "UniversalAttributesAccessibility_text4", + "value": "有accessibility有text btn123" + }, + { + "name": "UniversalAttributesAccessibility_text5", + "value": "文本1" + }, + { + "name": "UniversalAttributesAccessibility_text6", + "value": "文本2" + }, + { + "name": "UniversalAttributesAccessibility_text7", + "value": "分组" + }, + { + "name": "UniversalAttributesAccessibility_text8", + "value": "Column组件可以被选中,播报的内容是“分组”" + }, + { + "name": "UniversalAttributesAccessibility_text9", + "value": "文本3" + }, + { + "name": "UniversalAttributesAccessibility_text10", + "value": "文本4" + }, + { + "name": "UniversalAttributesAccessibility_text11", + "value": "通过EmbeddedComponent拉起EmbeddedUIExtensionAbility" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/background.png b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..847a0116481c5b7808d2373406eaf00d5fad1a6a --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,10 @@ +{ + "src": [ + "pages/Index", + "pages/IsolatedComponent/Extension", + "pages/EmbeddedComponent/Extension", + "pages/UIExtensionComponent/Extension", + "pages/ShowEmbeddedComponent/ShowPage", + "pages/UniversalAttributesAccessibility/VirtualNodeExample" + ] +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/dark/element/color.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/main/syscap.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..d14edde4277db282075a6639d65e40ddbbf0f2a2 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/main/syscap.json @@ -0,0 +1,20 @@ +{ + "devices": { + "general": [ + "default" + ], + "custom": [ + { + "xts": [ + "SystemCapability.ArkUI.ArkUI.Full", + "SystemCapability.ArkUI.ArkUI.Circle", + "SystemCapability.Test.UiTest", + "SystemCapability.Ability.AbilityRuntime.Core", + "SystemCapability.Notification.Emitter", + "SystemCapability.MiscServices.Time", + "SystemCapability.FileManagement.File.FileIO" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/mock/Libentry.mock.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..82fa70b5693ddab96d237d2d17d943d866b61465 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const NativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default NativeMock; \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/mock/mock-config.json5 b/ArkUIKit/UIExtensionAndAccessibility/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..98b0ae79f0090e1fc381d54c959fb32c9f7563f4 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/mock/mock-config.json5 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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 abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/module.json5 b/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..84d30586d591412f4252801cc483bbc6d8554104 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/syscap.json b/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/syscap.json new file mode 100644 index 0000000000000000000000000000000000000000..d14edde4277db282075a6639d65e40ddbbf0f2a2 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/entry/src/ohosTest/syscap.json @@ -0,0 +1,20 @@ +{ + "devices": { + "general": [ + "default" + ], + "custom": [ + { + "xts": [ + "SystemCapability.ArkUI.ArkUI.Full", + "SystemCapability.ArkUI.ArkUI.Circle", + "SystemCapability.Test.UiTest", + "SystemCapability.Ability.AbilityRuntime.Core", + "SystemCapability.Notification.Emitter", + "SystemCapability.MiscServices.Time", + "SystemCapability.FileManagement.File.FileIO" + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/entry/src/test/List.test.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/entry/src/test/LocalUnit.test.ets b/ArkUIKit/UIExtensionAndAccessibility/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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/UIExtensionAndAccessibility/hvigor/hvigor-config.json5 b/ArkUIKit/UIExtensionAndAccessibility/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/hvigor/hvigor-config.json5 @@ -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. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/hvigorfile.ts b/ArkUIKit/UIExtensionAndAccessibility/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..2a5e543f190732c159beb574dfc9fa37bc94e156 --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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. */ +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/oh-package.json5 b/ArkUIKit/UIExtensionAndAccessibility/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/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": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/UIExtensionAndAccessibility/ohosTest.md b/ArkUIKit/UIExtensionAndAccessibility/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..6fd4d7997abf069bf500c2f85018232c82795a6b --- /dev/null +++ b/ArkUIKit/UIExtensionAndAccessibility/ohosTest.md @@ -0,0 +1,18 @@ +# UIExtensionAndAccessibility 测试用例归档 + +## 用例表 + +|测试功能|预置条件|输入|预期输出|是否自动|测试结果| +|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| +|拉起应用| 设备正常运行| |成功拉起应用|是|Pass| +|查看预览界面ListenItem| 进入预览界面 | |ListenItem|是|Pass| +|查看UIExtensionComponent界面ListenItem| 进入UIExtensionComponent界面 | |ListenItem|是|Pass| +|查看EmbeddedComponent界面ListenItem| 进入EmbeddedComponent界面 | |ListenItem|是|Pass| +|查看IsolatedComponent界面ListenItem| 进入FullScreenLaunchComponent界面 | |ListenItem|是|Pass| +|查看FullScreenLaunchComponent界面ListenItem| 进入FullScreenLaunchComponent界面 | |ListenItem|是|Pass| +|查看ArkUI 无障碍能力界面ListenItem| 进入FullScreenLaunchComponent界面 | |ListenItem|是|Pass| +|UIExtensionComponent 组件页面| 点击 使用UIExtensionComponent 组件 | |进入 使用UIExtensionComponent 组件页面|是|Pass| +|EmbeddedComponent 组件页面| 点击 使用EmbeddedComponent 组件 | |进入 使用EmbeddedComponent 组件页面|是|Pass| +|IsolatedComponent 组件页面| 点击 使用IsolatedComponent 组件 | |进入 使用IsolatedComponent 组件页面|是|Pass| +|FullScreenLaunchComponent 组件页面| 点 击使用FullScreenLaunchComponent 组件 | |进入 使用FullScreenLaunchComponent 组件页面|是|Pass| +|ArkUI 无障碍能力页面| 点击 使用EmbeddedComponent 组件 | |进入 ArkUI 无障碍能力页面|是|Pass| \ No newline at end of file diff --git a/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/Embedded.png b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/Embedded.png new file mode 100644 index 0000000000000000000000000000000000000000..3e99233f5fa8c41c81d96cdca68841b35a153236 Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/Embedded.png differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image1.jpg b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e178f64fb7b3bd2cfcf29348e00a6f044b229628 Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image1.jpg differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image2.jpg b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..93997d2dd5f18ceeb1ac711adf6837d36f88c695 Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image2.jpg differ diff --git a/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image3.jpg b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..22129b9ba6825b9aab6448794b0f5370f6aba94d Binary files /dev/null and b/ArkUIKit/UIExtensionAndAccessibility/screenshots/device/image3.jpg differ diff --git a/ArkUIKit/Watch/AppScope/app.json5 b/ArkUIKit/Watch/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..2c1aa2fa516fb5a9c6391c9db70ae1a73cc673fb --- /dev/null +++ b/ArkUIKit/Watch/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.samples.watch", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/Watch/AppScope/resources/base/element/string.json b/ArkUIKit/Watch/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..555c205a657843771b9f13dcd4fd948a37413e18 --- /dev/null +++ b/ArkUIKit/Watch/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "watch" + } + ] +} diff --git a/ArkUIKit/Watch/AppScope/resources/base/media/background.png b/ArkUIKit/Watch/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/Watch/AppScope/resources/base/media/background.png differ diff --git a/ArkUIKit/Watch/AppScope/resources/base/media/foreground.png b/ArkUIKit/Watch/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ArkUIKit/Watch/AppScope/resources/base/media/foreground.png differ diff --git a/ArkUIKit/Watch/AppScope/resources/base/media/layered_image.json b/ArkUIKit/Watch/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/README_zh.md b/ArkUIKit/Watch/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..f683da48d52056a3da84450f9921d0dc2a8e3fac --- /dev/null +++ b/ArkUIKit/Watch/README_zh.md @@ -0,0 +1,73 @@ +# ArkUI使用动效组件指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitcode.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [@Watch装饰器](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/state-management/arkts-watch.md)。 + + +### 效果预览 + +| 首页 | +|------------------------------------| +| ![](screenshots/device/image1.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +|---pages +| |---Index.ets // 应用主页面 +| |---CountModifier.ets // @Watch和自定义组件更新 +| |---BasketModifier.ets // @Watch与@Link组合使用 +| |---ParentComponent.ets // @Watch的触发时机 +| |---UsePropertyName.ets // 使用changedPropertyName进行不同的逻辑处理 +entry/src/ohosTest/ +|---ets +| |---test +| | |---Ability.test.ets // @Watch装饰器示例代码测试代码 +``` +### 具体实现 +1. @Watch装饰器:@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当严格相等判断的结果是false(即不相等)的情况下,就会触发@Watch的回调。源码参考[watch/pages/Index.ets](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkUISample/Watch/entry/src/main/ets/pages/Index.ets) + * @Watch和自定义组件更新。展示组件更新和@Watch的处理步骤。count在CountModifier中由@State装饰,在TotalView中由@Prop装饰。 + * @Watch与@Link组合使用。展示如何在子组件中观察@Link变量。 + * @Watch的触发时机。展示@Watch回调触发时间是根据状态变量真正变化的时间,本示例在子组件中同时使用@Link和@ObjectLink装饰器,分别观察不同的状态对象。通过在父组件中更改状态变量并观察@Watch回调的先后顺序,来表明@Watch触发的时机与赋值、同步的关系。 + * 使用changedPropertyName进行不同的逻辑处理。说明了如何在@Watch函数中使用changedPropertyName进行不同的逻辑处理。 +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行, 支持设备:RK3568。 + +2.本示例为Stage模型,支持API20版本SDK,版本号:6.0.0.33,镜像版本号:OpenHarmony_6.0.0.33。 + +3.本示例需要使用DevEco Studio 6.0.0 Canary1 (Build Version: 6.0.0.270, built on May 9, 2025)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUISample/Watch > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples +git pull origin master +```` \ No newline at end of file diff --git a/ArkUIKit/Watch/build-profile.json5 b/ArkUIKit/Watch/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5438b5af2bf3d6d899ca5f90fcc048bd3f4775dc --- /dev/null +++ b/ArkUIKit/Watch/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + "signingConfigs": [] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/Watch/code-linter.json5 b/ArkUIKit/Watch/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/ArkUIKit/Watch/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/build-profile.json5 b/ArkUIKit/Watch/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f --- /dev/null +++ b/ArkUIKit/Watch/entry/build-profile.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. + */ +{ + "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/Watch/entry/hvigorfile.ts b/ArkUIKit/Watch/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/obfuscation-rules.txt b/ArkUIKit/Watch/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/oh-package.json5 b/ArkUIKit/Watch/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a --- /dev/null +++ b/ArkUIKit/Watch/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUIKit/Watch/entry/src/main/ets/common/resource.ets b/ArkUIKit/Watch/entry/src/main/ets/common/resource.ets new file mode 100644 index 0000000000000000000000000000000000000000..723a394265ee2e6bf6d895e9503c4b2d8e49207a --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/common/resource.ets @@ -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. + */ + +export class P2PManager { + public resourceToString(resource: Resource): string { + return getContext(this).resourceManager.getStringSync(resource); + } +} + +// 默认导出let +let p2pManager = new P2PManager(); + +export default p2pManager as P2PManager; \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/Watch/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/entryability/EntryAbility.ets @@ -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. + */ + +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 { + // Main window is created, set main page for this ability + 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 { + // 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/Watch/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/Watch/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/src/main/ets/pages/BasketModifier.ets b/ArkUIKit/Watch/entry/src/main/ets/pages/BasketModifier.ets new file mode 100644 index 0000000000000000000000000000000000000000..40dca6790938ac8c1fa4cbedea8dbb82dd366a35 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/pages/BasketModifier.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. + */ +// [Start basket_modifier] +class PurchaseItem { + public static nextId: number = 0; + public id: number; + public price: number; + + constructor(price: number) { + this.id = PurchaseItem.nextId++; + this.price = price; + } +} + +@Component +struct BasketViewer { + @Link @Watch('onBasketUpdated') shopBasket: PurchaseItem[]; + @State totalPurchase: number = 0; + + updateTotal(): number { + let total = this.shopBasket.reduce((sum, i) => sum + i.price, 0); + // 超过100欧元可享受折扣 + if (total >= 100) { + total = 0.9 * total; + } + return total; + } + + // @Watch 回调 + onBasketUpdated(propName: string): void { + this.totalPurchase = this.updateTotal(); + } + + build() { + Column() { + ForEach(this.shopBasket, + (item: PurchaseItem) => { + Text(`Price: ${item.price.toFixed(2)} €`); + }, + (item: PurchaseItem) => item.id.toString() + ) + Text(`Total: ${this.totalPurchase.toFixed(2)} €`); + } + } +} + +@Entry +@Component +struct BasketModifier { + @State shopBasket: PurchaseItem[] = []; + + build() { + Column() { + Button('Add to basket') + .onClick(() => { + this.shopBasket.push(new PurchaseItem(Math.round(100 * Math.random()))); + }) + BasketViewer({ shopBasket: $shopBasket }) + } + } +} + +// [End basket_modifier] \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/ets/pages/CountModifier.ets b/ArkUIKit/Watch/entry/src/main/ets/pages/CountModifier.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c511a87cd874c7ef51ea767beaeced5329973ff --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/pages/CountModifier.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. + */ +// [Start count_modifier] +@Component +struct TotalView { + @Prop @Watch('onCountUpdated') count: number = 0; + @State total: number = 0; + + // @Watch 回调 + onCountUpdated(propName: string): void { + this.total += this.count; + } + + build() { + Text(`Total: ${this.total}`); + } +} + +@Entry +@Component +struct CountModifier { + @State count: number = 0; + + build() { + Column() { + Button('add to basket') + .onClick(() => { + this.count++ + }) + TotalView({ count: this.count }); + } + } +} + +// [End count_modifier] \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/ets/pages/Index.ets b/ArkUIKit/Watch/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..e5ca110382df92d0db005aed7677e25a140a94b9 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/pages/Index.ets @@ -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. + */ +import { common } from '@kit.AbilityKit'; + +interface Ary { + path: string, + name: string +} + +@Entry +@Component +struct Index { + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + ary: Ary[] = [ + { + name: this.context.resourceManager.getStringByNameSync('watch_text1'), + path: 'pages/CountModifier' + }, + { + name: this.context.resourceManager.getStringByNameSync('watch_text2'), + path: 'pages/BasketModifier' + }, + { + name: this.context.resourceManager.getStringByNameSync('watch_text3'), + path: 'pages/ParentComponent' + }, + { + name: this.context.resourceManager.getStringByNameSync('watch_text4'), + path: 'pages/UsePropertyName' + }, + ] + + build() { + Scroll() { + Column({ space: 10 }) { + ForEach(this.ary, (item: Ary) => { + Button(item.name) + .onClick(() => this.getUIContext().getRouter().pushUrl({ url: item.path })); + }, (item: Ary) => item.name) + } + .width('100%') + } + } +} \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/ets/pages/ParentComponent.ets b/ArkUIKit/Watch/entry/src/main/ets/pages/ParentComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..cd65f0e6e840f482559c24ffc205623d42881808 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/pages/ParentComponent.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. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { common } from '@kit.AbilityKit'; +import resource from '../common/resource'; + +// [Start parent_component] +@Observed +class Task { + public isFinished: boolean = false; + + constructor(isFinished: boolean) { + this.isFinished = isFinished; + } +} +const DOMAIN = 0x0000; + +@Entry +@Component +struct ParentComponent { + @State @Watch('onTaskAChanged') taskA: Task = new Task(false); + @State @Watch('onTaskBChanged') taskB: Task = new Task(false); + // [StartExclude parent_component] + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + @State type1: string = this.context!.resourceManager.getStringSync($r('app.string.watch_text5').id); + @State type2: string = this.context!.resourceManager.getStringSync($r('app.string.watch_text6').id); + // [EndExclude parent_component] + + onTaskAChanged(changedPropertyName: string): void { + hilog.info(DOMAIN, resource.resourceToString($r('app.string.watch_text12')), + JSON.stringify(changedPropertyName)); + } + + onTaskBChanged(changedPropertyName: string): void { + hilog.info(DOMAIN, resource.resourceToString($r('app.string.watch_text12')), + JSON.stringify(changedPropertyName)); + + } + + build() { + Column() { + Text(`${this.type1} ${this.taskA.isFinished ? resource.resourceToString($r('app.string.watch_text7')) : resource.resourceToString($r('app.string.watch_text8'))}`); + Text(`${this.type2} ${this.taskB.isFinished ? resource.resourceToString($r('app.string.watch_text7')) : resource.resourceToString($r('app.string.watch_text8'))}`); + ChildComponent({ taskA: this.taskA, taskB: this.taskB }) + Button(resource.resourceToString($r('app.string.watch_text9'))) + .onClick(() => { + this.taskB = new Task(!this.taskB.isFinished); + this.taskA = new Task(!this.taskA.isFinished); + }) + } + } +} + +@Component +struct ChildComponent { + @ObjectLink @Watch('onObjectLinkTaskChanged') taskB: Task; + @Link @Watch('onLinkTaskChanged') taskA: Task; + // [StartExclude parent_component] + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + @State type1: string = this.context!.resourceManager.getStringSync($r('app.string.watch_text10').id); + @State type2: string = this.context!.resourceManager.getStringSync($r('app.string.watch_text11').id); + // [EndExclude parent_component] + + onObjectLinkTaskChanged(changedPropertyName: string): void { + hilog.info(DOMAIN, resource.resourceToString($r('app.string.watch_text13')), + JSON.stringify(changedPropertyName)); + } + + onLinkTaskChanged(changedPropertyName: string): void { + hilog.info(DOMAIN, resource.resourceToString($r('app.string.watch_text14')), + JSON.stringify(changedPropertyName)); + } + + build() { + Column() { + Text(`${this.type1} ${this.taskA.isFinished ? resource.resourceToString($r('app.string.watch_text7')) : resource.resourceToString($r('app.string.watch_text8'))}`); + Text(`${this.type2} ${this.taskB.isFinished ? resource.resourceToString($r('app.string.watch_text7')) : resource.resourceToString($r('app.string.watch_text8'))}`); + } + } +} + +// [End parent_component] \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/ets/pages/UsePropertyName.ets b/ArkUIKit/Watch/entry/src/main/ets/pages/UsePropertyName.ets new file mode 100644 index 0000000000000000000000000000000000000000..4e51f120f74aba4a3d9653a3591ab443d2a30a71 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/ets/pages/UsePropertyName.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. + */ +// [Start use_property_name] +@Entry +@Component +struct UsePropertyName { + @State @Watch('countUpdated') apple: number = 0; + @State @Watch('countUpdated') cabbage: number = 0; + @State fruit: number = 0; + + // @Watch 回调 + countUpdated(propName: string): void { + if (propName === 'apple') { + this.fruit = this.apple; + } + } + + build() { + Column() { + Text(`Number of apples: ${this.apple.toString()}`).fontSize(30); + Text(`Number of cabbages: ${this.cabbage.toString()}`).fontSize(30); + Text(`Total number of fruits: ${this.fruit.toString()}`).fontSize(30); + Button('Add apples') + .onClick(() => { + this.apple++; + }) + Button('Add cabbages') + .onClick(() => { + this.cabbage++; + }) + } + } +} + +// [End use_property_name] \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/module.json5 b/ArkUIKit/Watch/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..48003bfc257d2a69115144f9564906f623ea981d --- /dev/null +++ b/ArkUIKit/Watch/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": [ + "phone", + "tablet", + "2in1" + ], + "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/Watch/entry/src/main/resources/base/element/color.json b/ArkUIKit/Watch/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/src/main/resources/base/element/float.json b/ArkUIKit/Watch/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/ArkUIKit/Watch/entry/src/main/resources/base/element/string.json b/ArkUIKit/Watch/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..00c73bdb736d2e4bd9d3e2a6d3029e6c4c25b28e --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/resources/base/element/string.json @@ -0,0 +1,72 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Watch" + }, + { + "name": "watch_text1", + "value": "@Watch和自定义组件更新" + }, + { + "name": "watch_text2", + "value": "@Watch与@Link组合使用" + }, + { + "name": "watch_text3", + "value": "@Watch的触发时机" + }, + { + "name": "watch_text4", + "value": "使用changedPropertyName进行不同的逻辑处理" + }, + { + "name": "watch_text5", + "value": "父组件任务A状态:" + }, + { + "name": "watch_text6", + "value": "父组件任务B状态:" + }, + { + "name": "watch_text7", + "value": "已完成" + }, + { + "name": "watch_text8", + "value": "未完成" + }, + { + "name": "watch_text9", + "value": "切换任务状态" + }, + { + "name": "watch_text10", + "value": "子组件任务A状态:" + }, + { + "name": "watch_text11", + "value": "子组件任务B状态:" + }, + { + "name": "watch_text12", + "value": "观测到父组件任务属性变化:" + }, + { + "name": "watch_text13", + "value": "观测到子组件@ObjectLink关联的任务属性变化:" + }, + { + "name": "watch_text14", + "value": "观测到子组件@Link关联的任务属性变化:" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/main/resources/base/media/background.png b/ArkUIKit/Watch/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/Watch/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/Watch/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/Watch/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/Watch/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/Watch/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/Watch/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/Watch/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/Watch/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/Watch/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/Watch/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/Watch/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..105a05f9d09fc78513af69d7e77c39c8674ede2d --- /dev/null +++ b/ArkUIKit/Watch/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,9 @@ +{ + "src": [ + "pages/Index", + "pages/CountModifier", + "pages/BasketModifier", + "pages/ParentComponent", + "pages/UsePropertyName" + ] +} diff --git a/ArkUIKit/Watch/entry/src/main/resources/dark/element/color.json b/ArkUIKit/Watch/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/src/mock/mock-config.json5 b/ArkUIKit/Watch/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..323d1d611fecf4ecb751976e3a71500b3712a445 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * 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. + */ +{ +} \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/Watch/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5f6ec8657c596ab33dcc5cf361a57c4ccaecd075 --- /dev/null +++ b/ArkUIKit/Watch/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,147 @@ +/* + * 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, TestType, Level, Size, } from '@ohos/hypium'; +// 导入测试依赖kit +import { abilityDelegatorRegistry, Driver, ON, MatchPattern } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import resource from '../../../main/ets/common/resource'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; +const BUNDLE = 'Watch_'; +const TAG = '[Sample_Watch]'; +const DOMAIN = 0xF811; + +export default function abilityTest() { + describe('abilityTest', () => { + 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: Watch_AbilityTest_001 + * @tc.name: Watch_AbilityTest_001 + * @tc.desc: Set watch + * @tc.size: MediumTest + * @tc.type: Function + * @tc.level Level 1 + */ + it(BUNDLE + 'AbilityTest_001', 0, async () => { + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_001_begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.watch_text1')))); + await button1.click(); + await driver.delayMs(1000); + + let button2 = await driver.findComponent(ON.text('add to basket')); + await button2.click(); + await driver.delayMs(500); + await button2.click(); + await driver.delayMs(500); + await driver.pressBack(); + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_001_end'); + }) + + /* + * @tc.number: Watch_AbilityTest_002 + * @tc.name: Watch_AbilityTest_002 + * @tc.desc: Set watch + * @tc.size: MediumTest + * @tc.type: Function + * @tc.level Level 1 + */ + it(BUNDLE + 'AbilityTest_002', 0, async () => { + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_002_begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.watch_text2')), MatchPattern.CONTAINS)); + await button1.click(); + await driver.delayMs(1000); + + let button2 = await driver.findComponent(ON.text('Add to basket')); + await button2.click(); + await driver.delayMs(500); + await button2.click(); + await driver.delayMs(500); + await driver.pressBack(); + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_002_end'); + }) + + /* + * @tc.number: Watch_AbilityTest_003 + * @tc.name: Watch_AbilityTest_003 + * @tc.desc: Set watch + * @tc.size: MediumTest + * @tc.type: Function + * @tc.level Level 1 + */ + it(BUNDLE + 'AbilityTest_003', 0, async () => { + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_003_begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.watch_text3')), MatchPattern.CONTAINS)); + await button1.click(); + await driver.delayMs(1000); + + let button2 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.watch_text9')))); + await button2.click(); + await driver.delayMs(500); + await button2.click(); + await driver.delayMs(500); + await driver.pressBack(); + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_003_end'); + }) + + /* + * @tc.number: Watch_AbilityTest_004 + * @tc.name: Watch_AbilityTest_004 + * @tc.desc: Set watch + * @tc.size: MediumTest + * @tc.type: Function + * @tc.level Level 1 + */ + it(BUNDLE + 'AbilityTest_004', 0, async () => { + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_004_begin'); + let driver = Driver.create(); + let button1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.watch_text4')), MatchPattern.CONTAINS)); + await button1.click(); + await driver.delayMs(1000); + + let button2 = await driver.findComponent(ON.text('Add apples')); + await button2.click(); + await driver.delayMs(500); + await button2.click(); + await driver.delayMs(500); + + let button3 = await driver.findComponent(ON.text('Add cabbages')); + await button3.click(); + await driver.delayMs(500); + await button3.click(); + await driver.delayMs(500); + await driver.pressBack(); + hilog.info(DOMAIN, TAG, 'Watch_AbilityTest_004_end'); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/Watch/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ArkUIKit/Watch/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 abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ArkUIKit/Watch/entry/src/ohosTest/module.json5 b/ArkUIKit/Watch/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d3069fb7f9163da9f7e6ffe7366140c3368edc34 --- /dev/null +++ b/ArkUIKit/Watch/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": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUIKit/Watch/entry/src/test/List.test.ets b/ArkUIKit/Watch/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/entry/src/test/LocalUnit.test.ets b/ArkUIKit/Watch/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/Watch/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/Watch/hvigor/hvigor-config.json5 b/ArkUIKit/Watch/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/ArkUIKit/Watch/hvigor/hvigor-config.json5 @@ -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. + */ +{ + "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/Watch/hvigorfile.ts b/ArkUIKit/Watch/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/ArkUIKit/Watch/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ArkUIKit/Watch/oh-package.json5 b/ArkUIKit/Watch/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..837c0ff9f35a6bb9eea849fead7955c19bcdec8d --- /dev/null +++ b/ArkUIKit/Watch/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "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/Watch/ohosTest.md b/ArkUIKit/Watch/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..9569d1a8c364d58201fc20998e01bb45b69b23f7 --- /dev/null +++ b/ArkUIKit/Watch/ohosTest.md @@ -0,0 +1,7 @@ +# Watch 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|-------------------------| -------------- |----------------------|-------------| :------- | -------- | +| Watch装饰器示例代码验证 | 设备正常运行 | 进入各个示例代码页面,触发不同的动画效果 | 动画效果正常 | 是 | Pass | diff --git a/ArkUIKit/Watch/screenshots/device/image1.png b/ArkUIKit/Watch/screenshots/device/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..c181bc527ed0e5ec653871a0ebe896a958d90e14 Binary files /dev/null and b/ArkUIKit/Watch/screenshots/device/image1.png differ