diff --git a/ArkUISample/DialogProject/.gitignore b/ArkUISample/DialogProject/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ArkUISample/DialogProject/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/ArkUISample/DialogProject/AppScope/app.json5 b/ArkUISample/DialogProject/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4110d077eeaf58dc4671f31a7a6d846f9f2772f2 --- /dev/null +++ b/ArkUISample/DialogProject/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.dialogproject", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ArkUISample/DialogProject/AppScope/resources/base/element/string.json b/ArkUISample/DialogProject/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7aa13a433be744cff4bf694d53059c76e13ac56b --- /dev/null +++ b/ArkUISample/DialogProject/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "DialogProject" + } + ] +} diff --git a/ArkUISample/DialogProject/AppScope/resources/base/media/app_icon.png b/ArkUISample/DialogProject/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ArkUISample/DialogProject/AppScope/resources/base/media/app_icon.png differ diff --git a/ArkUISample/DialogProject/README_zh.md b/ArkUISample/DialogProject/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..23df86757f263887318ffcba8b7cdea3ea46b92e --- /dev/null +++ b/ArkUISample/DialogProject/README_zh.md @@ -0,0 +1,106 @@ +# ArkUI使用弹窗指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [不依赖UI组件的全局自定义弹出框 (openCustomDialog)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-uicontext-custom-dialog.md)。 +2. [基础自定义弹出框 (CustomDialog)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-common-components-custom-dialog.md)。 +3. [固定样式弹出框](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-fixes-style-dialog.md)。 +4. [菜单控制(Menu)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-popup-and-menu-components-menu.md) +5. [气泡提示 (Popup)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-popup-and-menu-components-popup.md) +6. [即时反馈 (Toast)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-create-toast.md) +### 效果预览 + +| 首页 | 弹窗类组件目录 | 自定义弹窗示例 | +|------------------------------------|------------------------------------|------------------------------------| +| ![](screenshots/device/image1.png) | ![](screenshots/device/image2.png) | ![](screenshots/device/image3.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +|---pages +| |---customdialog //自定义弹出框 +| | |---CreateCustomDialog.ets +| | |---DialogAnimation.ets +| | |---DialogInteraction.ets +| | |---DialogInteraction1.ets +| | |---DialogStyle.ets +| | |---Index.ets +| | |---NestDialog.ets +| |---fixedstyledialog //固定样式弹出框 +| | |---ActionSheet.ets +| | |---AlertDialog.ets +| | |---CalendarPickerDialog.ets +| | |---DatePickerDialog.ets +| | |---Index.ets +| | |---ShowActionMenu.ets +| | |---ShowDialog.ets +| | |---TextPickerDialog.ets +| | |---TimePickerDialog.ets +| |---Menu //菜单 +| | |---CreateMenu.ets +| | |---Index.ets +| |---opencustomdialog //不依赖UI组件的全局自定义弹出框 +| | |---Index.ets +| | |---openCustomDialog.ets +| |---popup //气泡提示 +| | |---ButtonPopup.ets +| | |---CustomPopup.ets +| | |---Index.ets +| | |---PopupAnimation.ets +| | |---PopupStateChange.ets +| | |---PopupStyle.ets +| | |---TextPrompts.ets +| |---Toast //即使反馈 +| | |---CreateToast.ets +| | |---Index.ets +| | |---OpenCloseToast.ets +|---pages +| |---Index.ets // 应用主页面 +| |---Index2.ets // 弹窗跳转页面 +entry/src/ohosTest/ +|---ets +| |---index.test.ets // 示例代码测试代码 +``` + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.1.0 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.1.0 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.1.0 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo ArkUISample/DialogProject > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/ArkUISample/DialogProject/build-profile.json5 b/ArkUISample/DialogProject/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..407b1cd9c40170066f910968ee92fae261ef8758 --- /dev/null +++ b/ArkUISample/DialogProject/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", + "compatibleSdkVersion": "5.1.0(18)", + "targetSdkVersion": "5.1.0(18)", + "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/ArkUISample/DialogProject/code-linter.json5 b/ArkUISample/DialogProject/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/.gitignore b/ArkUISample/DialogProject/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ArkUISample/DialogProject/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/build-profile.json5 b/ArkUISample/DialogProject/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ArkUISample/DialogProject/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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": { + }, + "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/ArkUISample/DialogProject/entry/hvigorfile.ts b/ArkUISample/DialogProject/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ArkUISample/DialogProject/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +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/ArkUISample/DialogProject/entry/obfuscation-rules.txt b/ArkUISample/DialogProject/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/oh-package.json5 b/ArkUISample/DialogProject/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUISample/DialogProject/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUISample/DialogProject/entry/src/main/ets/common/Card.ets b/ArkUISample/DialogProject/entry/src/main/ets/common/Card.ets new file mode 100644 index 0000000000000000000000000000000000000000..61df5e4555135254a0c0bada3738d5d7386d9dfc --- /dev/null +++ b/ArkUISample/DialogProject/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: ResourceStr; + @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/ArkUISample/DialogProject/entry/src/main/ets/common/PromptActionClass.ts b/ArkUISample/DialogProject/entry/src/main/ets/common/PromptActionClass.ts new file mode 100644 index 0000000000000000000000000000000000000000..b76828c66366e8118265b204c86b639463db7626 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/common/PromptActionClass.ts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// PromptActionClass.ts +// [Start open_close_update_custom_dialog] +import { BusinessError } from '@kit.BasicServicesKit'; +import { ComponentContent, window } from '@kit.ArkUI'; +import { UIContext } from '@ohos.arkui.UIContext'; + +export class PromptActionClass { + static ctx: UIContext; + static contentNode: ComponentContent; + static options: Object; + + static setContext(context: UIContext) { + this.ctx = context; + } + + static setContentNode(node: ComponentContent) { + this.contentNode = node; + } + + static setOptions(options: Object) { + this.options = options; + } + + // [Start call_open_custom_dialog] + static openDialog() { + if (this.contentNode !== null) { + this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.options) + .then(() => { + console.info('OpenCustomDialog complete.'); + }) + .catch((error: BusinessError) => { + let message = (error as BusinessError).message; + let code = (error as BusinessError).code; + console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`); + }) + } + } + // [End call_open_custom_dialog] + + // [Start call_close_custom_dialog] + static closeDialog() { + if (this.contentNode !== null) { + this.ctx.getPromptAction().closeCustomDialog(this.contentNode) + .then(() => { + console.info('CloseCustomDialog complete.'); + }) + .catch((error: BusinessError) => { + let message = (error as BusinessError).message; + let code = (error as BusinessError).code; + console.error(`CloseCustomDialog args error code is ${code}, message is ${message}`); + }) + } + } + // [End call_close_custom_dialog] + + // [Start update_custom_dialog_property] + static updateDialog(options: Object) { + if (this.contentNode !== null) { + this.ctx.getPromptAction().updateCustomDialog(this.contentNode, options) + .then(() => { + console.info('UpdateCustomDialog complete.'); + }) + .catch((error: BusinessError) => { + let message = (error as BusinessError).message; + let code = (error as BusinessError).code; + console.error(`UpdateCustomDialog args error code is ${code}, message is ${message}`); + }) + } + } + // [End update_custom_dialog_property] +} +// [End open_close_update_custom_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/common/Route.ets b/ArkUISample/DialogProject/entry/src/main/ets/common/Route.ets new file mode 100644 index 0000000000000000000000000000000000000000..859fec8c9ebd491e575d5baf8d43bd0512add60c --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/main/ets/common/resource.ets b/ArkUISample/DialogProject/entry/src/main/ets/common/resource.ets new file mode 100644 index 0000000000000000000000000000000000000000..723a394265ee2e6bf6d895e9503c4b2d8e49207a --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUISample/DialogProject/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..edc2839f203ba057c186e19b0cbbbf80c8faa8b3 --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUISample/DialogProject/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -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. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..fe681e20192036fe8007b063df001a2ce3566656 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 resource from '../common/resource'; +import { Route } from '../common/Route'; +import { CustomDestination, Custom_ROUTE_PREFIX } from './customdialog/Index'; +import { FixedDialogDestination, Fixed_ROUTE_PREFIX } from './fixedstyledialog/Index'; +import { MenuDestination, Menu_ROUTE_PREFIX } from './Menu/Index'; +import { CustomDialogDestination, CustomDialog_ROUTE_PREFIX } from './opencustomdialog/Index'; +import { PopupDestination, Popup_ROUTE_PREFIX } from './popup/Index'; +import { ToastDestination, Toast_ROUTE_PREFIX } from './Toast/Index'; + +const routes: Route[] = [ + { + title: resource.resourceToString($r('app.string.openCustomDialog')), + name: CustomDialog_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.CustomDialog1')), + name: Custom_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.FixedStyleDialog1')), + name: Fixed_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Menu1')), + name: Menu_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Toast1')), + name: Toast_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Popup1')), + name: Popup_ROUTE_PREFIX + } +]; + +@Builder +function Destination(name: string) { + if (name.startsWith(CustomDialog_ROUTE_PREFIX)) { + CustomDialogDestination(name); + } else if (name.startsWith(Custom_ROUTE_PREFIX)) { + CustomDestination(name); + } else if (name.startsWith(Fixed_ROUTE_PREFIX)) { + FixedDialogDestination(name); + } else if (name.startsWith(Menu_ROUTE_PREFIX)) { + MenuDestination(name); + } else if (name.startsWith(Toast_ROUTE_PREFIX)) { + ToastDestination(name); + } else if (name.startsWith(Popup_ROUTE_PREFIX)) { + PopupDestination(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() { + 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) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Index2.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Index2.ets new file mode 100644 index 0000000000000000000000000000000000000000..0573f0b09a3f09f30ececee30f17ce364289ac23 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Index2.ets @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start dialog_route_jump_back] +@Entry +@Component +struct Index2 { + @State message: ResourceStr = $r('app.string.back'); + build() { + Column() { + Button(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold).onClick(() => { + this.getUIContext().getRouter().back({ + url: '', + params: { + info: 'Hello World' + } + }); + }) + }.width('100%').height('100%').margin({ top: 20 }) + } +} +// [End dialog_route_jump_back] diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Menu/CreateMenu.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Menu/CreateMenu.ets new file mode 100644 index 0000000000000000000000000000000000000000..e6c8f9d3123eb4a748aa4871a0a9e1ec16aa2bb7 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Menu/CreateMenu.ets @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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'; + +// [Start builder_menu_content] +class Tmp { + private iconStr2: ResourceStr = $r('app.media.app_icon') + + set(val: Resource) { + this.iconStr2 = val; + } +} + +@Entry +@Component +export struct menuExample { + @State select: boolean = true; + private iconStr: ResourceStr = $r('app.media.app_icon'); + private iconStr2: ResourceStr = $r('app.media.app_icon'); + + @Builder + SubMenu() { + Menu() { + MenuItem({ content: 'copy', labelInfo: 'Ctrl+C' }) + MenuItem({ content: 'paste', labelInfo: 'Ctrl+V' }) + } + } + + @Builder + MyMenu() { + Menu() { + MenuItem({ startIcon: $r('app.media.app_icon'), content: $r('app.string.menu_single') }) + MenuItem({ startIcon: $r('app.media.app_icon'), content: $r('app.string.menu_forbid') }).enabled(false) + MenuItem({ + startIcon: this.iconStr, + content: $r('app.string.menu_more'), + endIcon: $r('app.media.app_icon'), + // 当builder参数进行配置时,表示与menuItem项绑定了子菜单。鼠标hover在该菜单项时,会显示子菜单。 + builder: this.SubMenu + }) + MenuItemGroup({ header: $r('app.string.menu_subtitle') }) { + MenuItem({ content: $r('app.string.menu_selection') }) + .selectIcon(true) + .selected(this.select) + .onChange((selected) => { + console.info('menuItem select' + selected); + let str: Tmp = new Tmp(); + str.set($r('app.media.app_icon')); + }) + MenuItem({ + startIcon: $r('app.media.app_icon'), + content: $r('app.string.menu_more'), + endIcon: $r('app.media.foreground'), + builder: this.SubMenu + }) + } + + MenuItem({ + startIcon: this.iconStr2, + content: $r('app.string.menu_single'), + endIcon: $r('app.media.app_icon') + }) + } + } + build() { + // [StartExclude builder_menu_content] + NavDestination() { + Column({ space: 12 }) { + + // [Start call_bind_menu] + Button($r('app.string.menu_default')) + .bindMenu([ + { + value: 'Menu1', + action: () => { + console.info('handle Menu1 select'); + } + } + ]) + // [End call_bind_menu] + .width(160) + .height(50) + + // [Start bind_menu_property] + Button($r('app.string.menu_bind')) + .bindMenu(this.MyMenu) + // [End bind_menu_property] + .width(160) + .height(50) + + // [Start create_right_click_menu] + Button($r('app.string.menu_rightClick')) + .bindContextMenu(this.MyMenu, ResponseType.RightClick) + // [End create_right_click_menu] + .width(160) + .height(50) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.create_menu')) + } + // [EndExclude builder_menu_content] +} +// [End builder_menu_content] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Menu/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Menu/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..55b4a25cc835351a284dbeec58f094f69016b35c --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Menu/Index.ets @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CompletedRoutableCard } from '../../common/Card'; +import resource from '../../common/resource'; +import { Route } from '../../common/Route'; +import { menuExample } from './CreateMenu'; + + +export const Menu_ROUTE_PREFIX: string = 'Menu_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Menu_ROUTE_PREFIX}/CreateMenu`, + title: resource.resourceToString($r('app.string.CreateMenu_title')), + description: $r('app.string.CreateMenu_des'), + } +] + +@Builder +export function MenuDestination(name: string) { + if (name === Menu_ROUTE_PREFIX) { + MenuExample(); + } else if (name === routes[0].name) { + menuExample(); + } +} + +@Entry +@Component +struct MenuExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.menu')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/CreateToast.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/CreateToast.ets new file mode 100644 index 0000000000000000000000000000000000000000..878844d16a59752fb3664e363cad27b69d7e9841 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/CreateToast.ets @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start create_toast] +import { PromptAction } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; + +@Entry +@Component +export struct CreateToastExample { + private uiContext: UIContext = this.getUIContext(); + private promptAction: PromptAction = this.uiContext.getPromptAction(); + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('Show toast').fontSize(20) + .onClick(() => { + try { + this.promptAction.showToast({ + message: 'Hello World', + duration: 2000 + }); + } catch (error) { + let message = (error as BusinessError).message; + let code = (error as BusinessError).code; + console.error(`showToast args error code is ${code}, message is ${message}`); + }; + }) + }.height('100%').width('100%').justifyContent(FlexAlign.Center) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CreateToast_title')) + } +} +// [End create_toast] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/DefaultAndTopToast.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/DefaultAndTopToast.ets new file mode 100644 index 0000000000000000000000000000000000000000..e9d631fbe14a324488563e0d30966bb3f885c9c4 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/DefaultAndTopToast.ets @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 +export struct DefaultAndTopToastExample { + private uiContext: UIContext = this.getUIContext(); + + build() { + NavDestination() { + Column({ space: 10 }) { + TextInput() + Column() { + Button() { + Text('DEFAULT Toast') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + } + .height(100) + .width('100%') + .onClick(() => { + promptAction.showToast({ + message: 'ok,I am DEFAULT toast', + duration: 2000, + showMode: promptAction.ToastShowMode.DEFAULT, + bottom: 80 + }) + }) + Blank().height(200); + Button() { + Text('TOPMOST Toast') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + } + .height(100) + .width('100%') + .onClick(() => { + promptAction.showToast({ + message: 'ok,I am TOP_MOST toast', + duration: 2000, + showMode: promptAction.ToastShowMode.TOP_MOST, + bottom: 85 + }) + }) + }.height('100%').width('100%').justifyContent(FlexAlign.Center) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + } +} diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..3015f8beb4b5fd8a5641ff45ca4e6aecb5e03a58 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/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 resource from '../../common/resource'; +import { Route } from '../../common/Route'; +import { CreateToastExample } from './CreateToast'; +import { OpenCloseToastExample } from './OpenCloseToast'; +import { DefaultAndTopToastExample } from './DefaultAndTopToast'; + +export const Toast_ROUTE_PREFIX: string = 'Toast_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Toast_ROUTE_PREFIX}/CreateToast`, + title: resource.resourceToString($r('app.string.CreateToast_title')), + description: $r('app.string.CreateToast_des'), + }, + { + name: `${Toast_ROUTE_PREFIX}/OpenCloseToast`, + title: resource.resourceToString($r('app.string.OpenCloseToast_title')), + description: $r('app.string.OpenCloseToast_des'), + }, + { + name: `${Toast_ROUTE_PREFIX}/DefaultAndTopToast`, + title: resource.resourceToString($r('app.string.DefaultAndTopToast_title')), + description: $r('app.string.DefaultAndTopToast_des'), + } +] + +@Builder +export function ToastDestination(name: string) { + if (name === Toast_ROUTE_PREFIX) { + ToastExample(); + } else if (name === routes[0].name) { + CreateToastExample(); + } else if (name === routes[1].name) { + OpenCloseToastExample(); + }else if (name === routes[2].name) { + DefaultAndTopToastExample(); + } +} + +@Entry +@Component +struct ToastExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.toast')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/OpenCloseToast.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/OpenCloseToast.ets new file mode 100644 index 0000000000000000000000000000000000000000..9633db89579574bda19e69512a15f9fc0115c5bb --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/Toast/OpenCloseToast.ets @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PromptAction } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; + +@Entry +@Component +export struct OpenCloseToastExample { + @State toastId: number = 0; + private uiContext: UIContext = this.getUIContext(); + private promptAction: PromptAction = this.uiContext.getPromptAction(); + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('Open Toast') + .height(100) + .onClick(() => { + try { + this.promptAction.openToast({ + message: 'Toast Massage', + duration: 10000, + }).then((toastId: number) => { + this.toastId = toastId; + }); + } catch (error) { + let message = (error as BusinessError).message; + let code = (error as BusinessError).code; + console.error(`OpenToast error code is ${code}, message is ${message}`); + }; + }) + Blank().height(50); + Button('Close Toast') + .height(100) + .onClick(() => { + try { + this.promptAction.closeToast(this.toastId); + } catch (error) { + let message = (error as BusinessError).message; + let code = (error as BusinessError).code; + console.error(`CloseToast error code is ${code}, message is ${message}`); + }; + }) + }.height('100%').width('100%').justifyContent(FlexAlign.Center) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.OpenCloseToast_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/CreateCustomDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/CreateCustomDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..55f609efe0d0a6dbe00f3e1543982c1e60af1b64 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/CreateCustomDialog.ets @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { PromptActionClass } from '../../common/PromptActionClass'; +import { ComponentContent } from '@kit.ArkUI'; + +// [Start create_custom_dialog_example] +@CustomDialog +struct CustomDialogExample { + controller: CustomDialogController = new CustomDialogController({ + builder: CustomDialogExample({}), + }) + + build() { + Column() { + Text($r('app.string.CustomDialog_dialog')) + } + .padding({ + top: 24, + left: 24, + bottom: 24, + right: 24 + }) + } +} +// [End create_custom_dialog_example] + +// [Start click_event_pop_dialog] +// [Start create_custom_dialog_controller] +@Entry +@Component +export struct CreateDialog { + dialogController: CustomDialogController = new CustomDialogController({ + builder: CustomDialogExample(), + }) + + // [StartExclude create_custom_dialog_controller] + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('click me') + .onClick(() => { + this.dialogController.open(); + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_create')) + } + // [EndExclude create_custom_dialog_controller] + // [End create_custom_dialog_controller] + // [End click_event_pop_dialog] +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogAnimation.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogAnimation.ets new file mode 100644 index 0000000000000000000000000000000000000000..e8a2125d334a42512265f2cdcfcc54fd66ebd4a8 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogAnimation.ets @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 set_dialog_animation] +@CustomDialog +struct CustomDialogExample { + controller?: CustomDialogController; + + build() { + Column() { + Text($r('app.string.CustomDialog_Animation')) + } + .padding({ + top: 24, + left: 24, + bottom: 24, + right: 24 + }) + } +} + +@Entry +@Component +export struct DialogAnimation { + @State textValue: string = ''; + @State inputValue: string = 'click me'; + dialogController: CustomDialogController | null = new CustomDialogController({ + builder: CustomDialogExample(), + openAnimation: { + duration: 1200, + curve: Curve.Friction, + delay: 500, + playMode: PlayMode.Alternate, + onFinish: () => { + console.info('play end'); + } + } + }) + + // 在自定义组件即将析构销毁时将dialogController置空 + aboutToDisappear() { + this.dialogController = null; // 将dialogController置空 + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button(this.inputValue) + .onClick(() => { + if (this.dialogController != null) { + this.dialogController.open(); + } + }).backgroundColor(0x317aff) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_Animation1')) + } +} +// [End set_dialog_animation] diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogInteraction.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogInteraction.ets new file mode 100644 index 0000000000000000000000000000000000000000..a9982e613173d1b893b5f79cc87e62a988942db2 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogInteraction.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. + */ + +import { PromptActionClass } from '../../common/PromptActionClass'; +import { ComponentContent } from '@kit.ArkUI'; + +// [Start custom_dialog_build_button] +@CustomDialog +struct CustomDialogExample { + cancel?: () => void; + confirm?: () => void; + controller: CustomDialogController; + + build() { + Column() { + Text('Please confirm your choice') + .padding({ top: 24, right: 24, left: 24 }) + Row({ space: 8 }) { + Button() { + Text('refuse') + .fontFamily('HarmonyHeiTi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + .lineHeight(21) + } + .onClick(() => { + this.controller.close(); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + + Button() { + Text('confirm') + .fontFamily('HarmonyHeiIi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + } + .onClick(() => { + this.controller.close(); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + }.padding({ top: 8, bottom: 16 }) + }.width(400) + + } +} +// [End custom_dialog_build_button] + +// [Start dialog_constructor_accept] +@Entry +@Component +export struct DialogInteraction { + dialogController: CustomDialogController = new CustomDialogController({ + builder: CustomDialogExample({ + cancel: () => { + this.onCancel(); + }, + confirm: () => { + this.onAccept(); + }, + }), + }) + + onCancel() { + console.info('Callback when the first button is clicked') + } + + onAccept() { + console.info('Callback when the second button is clicked') + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('click me') + .onClick(() => { + this.dialogController.open(); + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_interaction')) + } + // [End dialog_constructor_accept] +} diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogInteraction1.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogInteraction1.ets new file mode 100644 index 0000000000000000000000000000000000000000..f2d21b0f986528004cdc7809ffab842e841df639 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogInteraction1.ets @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 dialog_route_jump] +@CustomDialog +struct CustomDialogExample { + @Link textValue: string; + controller?: CustomDialogController; + cancel: () => void = () => { + }; + confirm: () => void = () => { + }; + + build() { + Column() { + if (this.textValue != '') { + Text(`The next content is:${this.textValue}`) + .padding({ top: 24, right: 24, left: 24 }) + } else { + Text('Whether to get the content of the second page') + .padding({ top: 24, right: 24, left: 24 }) + } + Row({ space: 8 }) { + Button() { + Text('refuse') + .fontFamily('HarmonyHeiTi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + .lineHeight(21) + } + .onClick(() => { + if (this.controller != undefined) { + this.controller.close(); + this.cancel(); + }; + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + + Button() { + Text('confirm') + .fontFamily('HarmonyHeiIi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + } + .onClick(() => { + if (this.controller != undefined && this.textValue != '') { + this.controller.close(); + } else if (this.controller != undefined) { + this.getUIContext().getRouter().pushUrl({ + url: 'pages/Index2' + }); + this.controller.close(); + } + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + } + .padding({ + top: 8, + bottom: 16, + left: 16, + right: 16 + }) + }.width(400) + + } +} + + +@Entry +@Component +export struct DialogInteraction1 { + @State textValue: string = '' + dialogController: CustomDialogController | null = new CustomDialogController({ + builder: CustomDialogExample({ + cancel: () => { + this.onCancel(); + }, + confirm: () => { + this.onAccept(); + }, + textValue: $textValue + }) + }) + + // 在自定义组件即将析构销毁时将dialogController置空 + aboutToDisappear() { + this.dialogController = null; // 将dialogController置空 + } + + onPageShow() { + const params = this.getUIContext().getRouter().getParams() as Record; // 获取传递过来的参数对象 + if (params) { + this.dialogController?.open(); + this.textValue = params.info as string; // 获取info属性的值 + } + } + + onCancel() { + console.info('Callback when the first button is clicked'); + } + + onAccept() { + console.info('Callback when the second button is clicked'); + } + + exitApp() { + console.info('Click the callback in the blank area'); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('click me') + .onClick(() => { + if (this.dialogController != null) { + this.dialogController.open(); + } + }).backgroundColor(0x317aff) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_interaction1')) + } +} +// [End dialog_route_jump] diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogStyle.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogStyle.ets new file mode 100644 index 0000000000000000000000000000000000000000..fe3cc88501af2c73e12c9372f76cf612a6495622 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/DialogStyle.ets @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start set_dialog_style] +@CustomDialog +struct CustomDialogExample { + controller?: CustomDialogController; + + build() { + Column() { + Text($r('app.string.CustomDialog_shadow')) + } + .padding({ + top: 24, + left: 24, + bottom: 24, + right: 24 + }) + } +} + +@Entry +@Component +export struct DialogStyle { + @State textValue: string = ''; + @State inputValue: string = 'click me'; + dialogController: CustomDialogController | null = new CustomDialogController({ + builder: CustomDialogExample(), + autoCancel: true, + alignment: DialogAlignment.Center, + offset: { dx: 0, dy: -20 }, + gridCount: 4, + customStyle: false, + backgroundColor: 0xd9ffffff, + cornerRadius: 20, + width: '80%', + height: '100px', + borderWidth: 2, + borderStyle: BorderStyle.Solid, //使用borderStyle属性,需要和borderWidth属性一起使用 + shadow: ({ + radius: 20, + color: Color.Grey, + offsetX: 50, + offsetY: 0 + }), + }) + + // 在自定义组件即将析构销毁时将dialogController置空 + aboutToDisappear() { + this.dialogController = null; // 将dialogController置空 + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button(this.inputValue) + .onClick(() => { + if (this.dialogController != null) { + this.dialogController.open(); + } + }).backgroundColor(0x317aff) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_style')) + } +} +// [End set_dialog_style] diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..c4df523d627c67a4e5b383aa8d43e79334da896f --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/Index.ets @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 resource from '../../common/resource'; +import { Route } from '../../common/Route'; +import { CreateDialog } from './CreateCustomDialog'; +import { DialogAnimation } from './DialogAnimation'; +import { DialogInteraction } from './DialogInteraction'; +import { DialogInteraction1 } from './DialogInteraction1'; +import { DialogStyle } from './DialogStyle'; +import { NestDialog } from './NestDialog'; + +export const Custom_ROUTE_PREFIX: string = 'Custom_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Custom_ROUTE_PREFIX}/dialog`, + title: resource.resourceToString($r('app.string.CustomDialog_create_title')), + description: $r('app.string.CustomDialog_create_des'), + }, + { + name: `${Custom_ROUTE_PREFIX}/dialoginteraction`, + title: resource.resourceToString($r('app.string.CustomDialog_interaction_title')), + description: $r('app.string.CustomDialog_interaction_des'), + }, + { + name: `${Custom_ROUTE_PREFIX}/dialoginteraction1`, + title: resource.resourceToString($r('app.string.CustomDialog_interaction1_title')), + description: $r('app.string.CustomDialog_interaction1_des'), + }, + { + name: `${Custom_ROUTE_PREFIX}/DialogAnimation`, + title: resource.resourceToString($r('app.string.CustomDialog_animation_title')), + description: $r('app.string.CustomDialog_animation_des'), + }, + { + name: `${Custom_ROUTE_PREFIX}/DialogStyle`, + title: resource.resourceToString($r('app.string.CustomDialog_Style_title')), + description: $r('app.string.CustomDialog_Style_des'), + }, + { + name: `${Custom_ROUTE_PREFIX}/NestDialog`, + title: resource.resourceToString($r('app.string.CustomDialog_nest')), + description: $r('app.string.CustomDialog_nest_des'), + } +] + +@Builder +export function CustomDestination(name: string) { + if (name === Custom_ROUTE_PREFIX) { + CustomExample(); + } else if (name === routes[0].name) { + CreateDialog(); + } else if (name === routes[1].name) { + DialogInteraction(); + } else if (name === routes[2].name) { + DialogInteraction1(); + } else if (name === routes[3].name) { + DialogAnimation(); + } else if (name === routes[4].name) { + DialogStyle(); + } else if (name === routes[5].name) { + NestDialog(); + } +} + +@Entry +@Component +struct CustomExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.CustomDialog_dialog')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/NestDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/NestDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..5ce2b1ffb785052718478ba3a1b73d2d725860ba --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/customdialog/NestDialog.ets @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 set_dialog_nest] +@CustomDialog +struct CustomDialogExampleTwo { + controllerTwo?: CustomDialogController; + @State message: string = 'I am the second dialog box.'; + @State showIf: boolean = false; + + build() { + Column() { + Text('this is the second dialog') + .padding({ top: 24, right: 24, left: 24 }) + Row({ space: 8 }) { + Button() { + Text('close dialog') + .fontFamily('HarmonyHeiTi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + .lineHeight(21) + } + .onClick(() => { + this.controllerTwo?.close(); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(360) + .height(40) + } + .padding({ + top: 8, + bottom: 16, + left: 16, + right: 16 + }) + }.width(400) + + } +} + +@CustomDialog +struct CustomDialogExample { + openSecondBox?: () => void; + controller?: CustomDialogController; + + build() { + Column() { + Text('Click Confirm to open the second dialog') + .padding({ top: 24, right: 24, left: 24 }) + Row({ space: 8 }) { + Button() { + Text('refuse') + .fontFamily('HarmonyHeiTi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + .lineHeight(21) + } + .onClick(() => { + this.controller?.close(); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + + Button() { + Text('confirm') + .fontFamily('HarmonyHeiIi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + } + .onClick(() => { + this.controller!.close(); + this.openSecondBox!(); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + } + .padding({ + top: 8, + bottom: 16, + left: 16, + right: 16 + }) + }.width(400) + + } +} + +@Entry +@Component +export struct NestDialog { + @State inputValue: string = 'Click Me'; + dialogController: CustomDialogController | null = new CustomDialogController({ + builder: CustomDialogExample({ + openSecondBox: () => { + if (this.dialogControllerTwo != null) { + this.dialogControllerTwo.open() + } + } + }), + cancel: this.exitApp, + autoCancel: true, + alignment: DialogAlignment.Center, + offset: { dx: 0, dy: -20 }, + gridCount: 4, + customStyle: false + }) + dialogControllerTwo: CustomDialogController | null = new CustomDialogController({ + builder: CustomDialogExampleTwo(), + alignment: DialogAlignment.Center, + offset: { dx: 0, dy: -25 } + }) + + aboutToDisappear() { + this.dialogController = null; + this.dialogControllerTwo = null; + } + + onCancel() { + console.info('Callback when the first button is clicked'); + } + + onAccept() { + console.info('Callback when the second button is clicked'); + } + + exitApp() { + console.info('Click the callback in the blank area'); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button(this.inputValue) + .onClick(() => { + if (this.dialogController != null) { + this.dialogController.open(); + } + }).backgroundColor(0x317aff) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_nest')) + } +} +// [End set_dialog_nest] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ActionSheet.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ActionSheet.ets new file mode 100644 index 0000000000000000000000000000000000000000..edc3baea8251f17286cc909df2d52b26188d1a94 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ActionSheet.ets @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 action_sheet_dialog] +@Entry +@Component +export struct showActionSheetExample { + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('showActionSheet') + .margin(30) + .onClick(() => { + this.getUIContext().showActionSheet({ + title: 'ActionSheet title', + message: 'message', + autoCancel: false, + width: 300, + height: 300, + cornerRadius: 20, + borderWidth: 1, + borderStyle: BorderStyle.Solid, + borderColor: Color.Blue, + backgroundColor: Color.White, + transition: TransitionEffect.asymmetric(TransitionEffect.OPACITY + .animation({ duration: 3000, curve: Curve.Sharp }) + .combine(TransitionEffect.scale({ x: 1.5, y: 1.5 }) + .animation({ duration: 3000, curve: Curve.Sharp })), + TransitionEffect.OPACITY.animation({ duration: 100, curve: Curve.Smooth }) + .combine(TransitionEffect.scale({ x: 0.5, y: 0.5 }) + .animation({ duration: 100, curve: Curve.Smooth }))), + confirm: { + value: 'Confirm button', + action: () => { + console.info('Get Alert Dialog handled'); + } + }, + alignment: DialogAlignment.Center, + sheets: [ + { + title: 'apples', + action: () => { + } + }, + { + title: 'bananas', + action: () => { + } + }, + { + title: 'pears', + action: () => { + console.log('pears'); + } + } + ] + }) + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_ActionSheet')) + } +} +// [End action_sheet_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/AlertDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/AlertDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..825c1f7ed93b7d661c5f189dd8687986f9fd4156 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/AlertDialog.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 alert_dialog] +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct showAlertDialogExample { + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('showAlertDialog') + .margin(30) + .onClick(() => { + this.getUIContext().showAlertDialog( + { + title: 'title', + message: 'text', + autoCancel: true, + alignment: DialogAlignment.Center, + offset: { dx: 0, dy: -20 }, + gridCount: 3, + transition: TransitionEffect.asymmetric(TransitionEffect.OPACITY + .animation({ duration: 3000, curve: Curve.Sharp }) + .combine(TransitionEffect.scale({ x: 1.5, y: 1.5 }) + .animation({ duration: 3000, curve: Curve.Sharp })), + TransitionEffect.OPACITY.animation({ duration: 100, curve: Curve.Smooth }) + .combine(TransitionEffect.scale({ x: 0.5, y: 0.5 }) + .animation({ duration: 100, curve: Curve.Smooth }))), + buttons: [{ + value: 'cancel', + action: () => { + console.info('Callback when the first button is clicked'); + } + }, + { + enabled: true, + defaultFocus: true, + style: DialogButtonStyle.HIGHLIGHT, + value: 'ok', + action: () => { + console.info('Callback when the second button is clicked'); + } + }], + } + ) + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_AlertDialog')) + } +} +// [End alert_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/CalendarPickerDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/CalendarPickerDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..c12418f2f7f837b719ee5397d8abf7f582edab93 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/CalendarPickerDialog.ets @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start calender_picker_dialog] +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct CalendarDialog { + private selectedDate: Date = new Date('2024-04-23'); + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('Show CalendarPicker Dialog') + .margin(20) + .onClick(() => { + console.info('CalendarDialog.show'); + CalendarPickerDialog.show({ + selected: this.selectedDate, + acceptButtonStyle: { + fontColor: '#2787d9', + fontSize: '16fp', + backgroundColor: '#f7f7f7', + borderRadius: 10 + }, + cancelButtonStyle: { + fontColor: Color.Red, + fontSize: '16fp', + backgroundColor: '#f7f7f7', + borderRadius: 10 + }, + onAccept: (date: Date)=>{ + // 当弹出框再次弹出时显示选中的是上一次确定的日期 + this.selectedDate = date; + } + }) + }) + }.width('100%') + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_calender')) + } +} +// [End calender_picker_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/DatePickerDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/DatePickerDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..28caa25d66d07d063b681ea5dffbd8df5398b73b --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/DatePickerDialog.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start date_picker_dialog] +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct DatePickerDialogExample { + @State selectTime: Date = new Date('2023-12-25T08:30:00'); + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('showDatePickerDialog') + .margin(30) + .onClick(() => { + this.getUIContext().showDatePickerDialog({ + start: new Date('2000-1-1'), + end: new Date('2100-12-31'), + selected: this.selectTime, + lunarSwitch: true, + showTime: true, + onDateAccept: (value: Date) => { + this.selectTime = value; + console.info('DatePickerDialog:onAccept()' + JSON.stringify(value)); + }, + }) + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_date')) + } +} +// [End date_picker_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b8e1c07033025062a98b9ea0be8bee1349e05688 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/Index.ets @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { showActionSheetExample } from './ActionSheet'; +import { CalendarDialog } from './CalendarPickerDialog'; +import { DatePickerDialogExample } from './DatePickerDialog'; +import { TextPickerDialogExample } from './TextPickerDialog'; +import { TimePickerDialogExample } from './TimePickerDialog'; +import { showAlertDialogExample } from './AlertDialog'; +import { ShowActionMenuExample } from './ShowActionMenu'; +import { ShowDialogExample } from './ShowDialog'; +import resource from '../../common/resource'; + + +export const Fixed_ROUTE_PREFIX: string = 'Fixed_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Fixed_ROUTE_PREFIX}/CalendarPickerDialog`, + title: resource.resourceToString($r('app.string.CalendarPickerDialog_title')), + description: $r('app.string.CalendarPickerDialog_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/DatePickerDialogExample`, + title: resource.resourceToString($r('app.string.DatePicker_title')), + description: $r('app.string.DatePicker_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/TimePickerDialog`, + title: resource.resourceToString($r('app.string.TimePicker_title')), + description: $r('app.string.TimePicker_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/TextPickerDialog`, + title: resource.resourceToString($r('app.string.TextPicker_title')), + description: $r('app.string.TextPicker_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/ActionSheet`, + title: resource.resourceToString($r('app.string.ActionSheet_title')), + description: $r('app.string.ActionSheet_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/AlertDialog`, + title: resource.resourceToString($r('app.string.AlertDialog_title')), + description: $r('app.string.AlertDialog_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/ShowActionMenu`, + title: resource.resourceToString($r('app.string.ShowActionMenu_title')), + description: $r('app.string.ShowActionMenu_des'), + }, + { + name: `${Fixed_ROUTE_PREFIX}/ShowDialog`, + title: resource.resourceToString($r('app.string.ShowDialog_title')), + description: $r('app.string.ShowDialog_des'), + } +] + +@Builder +export function FixedDialogDestination(name: string) { + if (name === Fixed_ROUTE_PREFIX) { + FixedDialogExample(); + } else if (name === routes[0].name) { + CalendarDialog(); + } else if (name === routes[1].name) { + DatePickerDialogExample(); + } else if (name === routes[2].name) { + TimePickerDialogExample(); + } else if (name === routes[3].name) { + TextPickerDialogExample(); + } else if (name === routes[4].name) { + showActionSheetExample(); + } else if (name === routes[5].name) { + showAlertDialogExample(); + } else if (name === routes[6].name) { + ShowActionMenuExample(); + } else if (name === routes[7].name) { + ShowDialogExample(); + } +} + +@Entry +@Component +struct FixedDialogExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.fixed_dialog')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ShowActionMenu.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ShowActionMenu.ets new file mode 100644 index 0000000000000000000000000000000000000000..40845cae2f434200513155cc5346a90e8ba15a43 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ShowActionMenu.ets @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct ShowActionMenuExample { + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('ShowActionMenu') + .margin(30) + .onClick(() => { + let uiContext = this.getUIContext(); + let promptAction: PromptAction = uiContext.getPromptAction(); + try { + promptAction.showActionMenu({ + title: 'showActionMenu Title Info', + buttons: [ + { + text: 'item1', + color: '#666666' + }, + { + text: 'item2', + color: '#000000' + }, + ] + }) + .then(data => { + console.info('showActionMenu success, click button: ' + data.index); + }) + .catch((err: Error) => { + console.error('showActionMenu error: ' + err); + }) + } catch (error) { + } + }) + }.width('100%') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ShowActionMenu_title')) + } +} + diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ShowDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ShowDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..73da39ba000a77326b1c0093dbd8493e1755f7d8 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/ShowDialog.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 { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct ShowDialogExample { + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Button('ShowDialog') + .margin(30) + .onClick(() => { + let uiContext = this.getUIContext(); + let promptAction: PromptAction = uiContext.getPromptAction(); + try { + promptAction.showDialog({ + title: 'showDialog Title Info', + message: 'Message Info', + buttons: [ + { + text: 'button1', + color: '#000000' + }, + { + text: 'button2', + color: '#000000' + } + ] + }, (err, data) => { + if (err) { + console.error('showDialog err: ' + err); + return; + } + console.info('showDialog success callback, click button: ' + data.index); + }); + } catch (error) { + } + }) + }.width('100%') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ShowDialog_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/TextPickerDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/TextPickerDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..165285fbc1f7f2aba0988c88d2e2f3362c770aa0 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/TextPickerDialog.ets @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 text_picker_dialog] +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct TextPickerDialogExample { + private fruits: TextCascadePickerRangeContent[] = [ + { + text: 'United States', + children: [{ text: 'California', children: [{ text: 'Los Angeles' }, { text: 'San Francisco' }, { text: 'San Diego' }] }, + { text: 'Texas', children: [{ text: 'Houston' }, { text: 'Dallas' }, { text: 'Austin' }] }] + }, + { + text: 'Canada', + children: [{ text: 'Ontario', children: [{ text: 'Toronto' }, { text: 'Ottawa' }, { text: 'Hamilton' }] }, + { text: 'British Columbia', children: [{ text: 'Vancouver' }, { text: 'Victoria' }, { text: 'Kelowna' }] }] + }, + { + text: 'Australia', + children: [{ text: 'New South Wales', children: [{ text: 'Sydney' }, { text: 'Canberra' }, { text: 'Newcastle' }] }, + { text: 'Victoria', children: [{ text: 'Melbourne' }, { text: 'Geelong' }, { text: 'Ballarat' }] }] + } + ] + private select : number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('showTextPickerDialog') + .margin(30) + .onClick(() => { + this.getUIContext().showTextPickerDialog({ + range: this.fruits, + selected: this.select, + onAccept: (value: TextPickerResult) => { + this.select = value.index as number; + } + }) + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_text')) + } +} +// [End text_picker_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/TimePickerDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/TimePickerDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..7f0393367b4ae9594a1ea01c6ad12f8a11ff8c59 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/fixedstyledialog/TimePickerDialog.ets @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start time_picker_dialog] +import { PromptAction } from '@kit.ArkUI'; + +@Entry +@Component +export struct TimePickerDialogExample { + @State selectTime: Date = new Date('2023-12-25T08:30:00'); + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('showTimePickerDialog') + .margin(30) + .onClick(() => { + this.getUIContext().showTimePickerDialog({ + selected: this.selectTime, + textStyle: { color: '#2787d9', font: { size: '14fp', weight: FontWeight.Normal } }, + selectedTextStyle: { color: '#004aaf', font: { size: '18fp', weight: FontWeight.Regular } }, + acceptButtonStyle: { + fontColor: '#2787d9', + fontSize: '16fp', + backgroundColor: '#f7f7f7', + borderRadius: 10 + }, + cancelButtonStyle: { + fontColor: Color.Red, + fontSize: '16fp', + backgroundColor: '#f7f7f7', + borderRadius: 10 + } + }) + }) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomDialog_time')) + } +} +// [End time_picker_dialog] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/opencustomdialog/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/opencustomdialog/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..3d1b31b014ae9c8d588d06fd8b0f51aa5491e64b --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/opencustomdialog/Index.ets @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 resource from '../../common/resource'; +import { Route } from '../../common/Route'; +import { openCustomDialog } from './openCustomDialog'; + +export const CustomDialog_ROUTE_PREFIX: string = 'CustomDialog_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${CustomDialog_ROUTE_PREFIX}/Customdialog`, + title: resource.resourceToString($r('app.string.Customdialog_title')), + description: $r('app.string.Customdialog_des'), + } +] + +@Builder +export function CustomDialogDestination(name: string) { + if (name === CustomDialog_ROUTE_PREFIX) { + CustomDialogExample(); + } else if (name === routes[0].name) { + openCustomDialog(); + } +} + +@Entry +@Component +struct CustomDialogExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title('CustomDialog') + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/opencustomdialog/openCustomDialog.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/opencustomdialog/openCustomDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c65b64e1ef59c54bca7f93660fa1f1240079549 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/opencustomdialog/openCustomDialog.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. + */ + +// [Start open_close_component_content] +import { PromptActionClass } from '../../common/PromptActionClass'; +import { ComponentContent } from '@kit.ArkUI'; + +class Params { + private text: string = ''; + + constructor(text: string) { + this.text = text; + } +} + +@Builder +function buildText(params: Params) { + Column() { + Text($r('app.string.CustomDialog_dialog')) + .padding({ top: 24, right: 24, left: 24 }) + Row({ space: 8 }) { + Button() { + Text($r('app.string.close_dialog')) + .fontFamily('HarmonyHeiTi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + .lineHeight(21) + } + .onClick(() => { + setTimeout(() => { + PromptActionClass.updateDialog({ + alignment: DialogAlignment.Bottom, + offset: { dx: 0, dy: -50 } + }) + }, 1500); + PromptActionClass.closeDialog(); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + + Button() { + Text($r('app.string.change_dialog')) + .fontFamily('HarmonyHeiIi') + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + } + .onClick(() => { + setTimeout(() => { + PromptActionClass.updateDialog({ + alignment: DialogAlignment.Bottom, + offset: { dx: 0, dy: -50 } + }) + }, 150); + }) + .layoutWeight(1) + .backgroundColor(Color.Transparent) + .width(180) + .height(40) + } + .padding({ + top: 8, + bottom: 16, + left: 16, + right: 16 + }) + } + .width(400) + .backgroundColor('#FFF0F0F0') + .borderRadius(32) +} + +@Entry +@Component +export struct openCustomDialog { + @State message: string = 'hello' + private ctx: UIContext = this.getUIContext(); + // [Start create_component_content] + private contentNode: ComponentContent = + new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message)); + // [End create_component_content] + + aboutToAppear(): void { + PromptActionClass.setContext(this.ctx); + PromptActionClass.setContentNode(this.contentNode); + PromptActionClass.setOptions({ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } }); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Row() { + Column() { + Text($r('app.string.change_text')) + .fontSize(14) + .fontColor('#666') + Button('open dialog and update options') + .id('open') + .margin({ top: 10, bottom: 50 }) + .onClick(() => { + PromptActionClass.openDialog(); + }) + } + .width('100%') + .height('100%') + } + .height('100%') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.open_customDialog')) + } +} +// [End open_close_component_content] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/ButtonPopup.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/ButtonPopup.ets new file mode 100644 index 0000000000000000000000000000000000000000..114fc049e35955c71c3d11ac88db751f19cf9efb --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/ButtonPopup.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. + */ + +// [Start button_popup] +@Entry +@Component +export struct ButtonPopupExample { + @State handlePopup: boolean = false; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('PopupOptions').margin({ top: 300 }) + .onClick(() => { + this.handlePopup = !this.handlePopup; + }) + .bindPopup(this.handlePopup, { + message: 'This is a popup with PopupOptions', + primaryButton: { + value: 'Confirm', + action: () => { + this.handlePopup = !this.handlePopup; + console.info('confirm Button click'); + } + }, + secondaryButton: { + value: 'Cancel', + action: () => { + this.handlePopup = !this.handlePopup; + } + }, + onStateChange: (e) => { + if (!e.isVisible) { + this.handlePopup = false; + } + } + }) + }.width('100%').padding({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.button_popup')) + } +} +// [End button_popup] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/CustomPopup.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/CustomPopup.ets new file mode 100644 index 0000000000000000000000000000000000000000..c533a4f49056d7da52b8086304a12e3c1a6a0f5c --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/CustomPopup.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. + */ + +// [Start custom_popup] +@Entry +@Component +export struct CustomPopupExample { + @State customPopup: boolean = false; + + // popup构造器定义弹框内容 + @Builder + popupBuilder() { + Row({ space: 2 }) { + Image($r('app.media.app_icon')).width(24).height(24).margin({ left: 5 }) + Text('This is Custom Popup').fontSize(15) + }.width(200).height(50).padding(5) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('CustomPopupOptions') + .margin({ top: 300 }) + .onClick(() => { + this.customPopup = !this.customPopup; + }) + .bindPopup(this.customPopup, { + builder: this.popupBuilder, // 气泡的内容 + placement: Placement.Bottom, // 气泡的弹出位置 + popupColor: Color.Pink, // 气泡的背景色 + onStateChange: (e) => { + if (!e.isVisible) { + this.customPopup = false + } + } + }) + } + .height('100%') + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.custom_popup')) + } +} +// [End custom_popup] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/Index.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..dacaf1fb9426182336801f310698a27fd228a09e --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/Index.ets @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 resource from '../../common/resource'; +import { Route } from '../../common/Route'; +import { ButtonPopupExample } from './ButtonPopup'; +import { CustomPopupExample } from './CustomPopup'; +import { AnimationPopupExample } from './PopupAnimation'; +import { StatePopupExample } from './PopupStateChange'; +import { StylePopupExample } from './PopupStyle'; +import { TextPopupExample } from './TextPrompts'; + + +export const Popup_ROUTE_PREFIX: string = 'Popup_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Popup_ROUTE_PREFIX}/TextPopupExample`, + title: resource.resourceToString($r('app.string.TextPopup_title')), + description: $r('app.string.TextPopup_des'), + }, + { + name: `${Popup_ROUTE_PREFIX}/onStateChange`, + title: resource.resourceToString($r('app.string.onStateChange_title')), + description: $r('app.string.onStateChange_des'), + }, + { + name: `${Popup_ROUTE_PREFIX}/ButtonPopupExample`, + title: resource.resourceToString($r('app.string.ButtonPopup_title')), + description: $r('app.string.ButtonPopup_des'), + }, + { + name: `${Popup_ROUTE_PREFIX}/AnimationPopupExample`, + title: resource.resourceToString($r('app.string.AnimationPopup_title')), + description: $r('app.string.AnimationPopup_des'), + }, + { + name: `${Popup_ROUTE_PREFIX}/CustomPopupExample`, + title: resource.resourceToString($r('app.string.CustomPopup_title')), + description: $r('app.string.CustomPopup_des'), + }, + { + name: `${Popup_ROUTE_PREFIX}/StylePopupExample`, + title: resource.resourceToString($r('app.string.StylePopup_title')), + description: $r('app.string.StylePopup_des'), + } +] + +@Builder +export function PopupDestination(name: string) { + if (name === Popup_ROUTE_PREFIX) { + PopupExample(); + } else if (name === routes[0].name) { + TextPopupExample(); + } else if (name === routes[1].name) { + StatePopupExample(); + } else if (name === routes[2].name) { + ButtonPopupExample(); + } else if (name === routes[3].name) { + AnimationPopupExample(); + } else if (name === routes[4].name) { + CustomPopupExample(); + } else if (name === routes[5].name) { + StylePopupExample(); + } +} + +@Entry +@Component +struct PopupExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.popup')) + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupAnimation.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupAnimation.ets new file mode 100644 index 0000000000000000000000000000000000000000..2ef0e99f872fd0f9298ce1a88b6978aeff8f87a7 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupAnimation.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. + */ + +// [Start animation_popup] +@Entry +@Component +export struct AnimationPopupExample { + @State handlePopup: boolean = false; + @State customPopup: boolean = false; + + @Builder popupBuilder() { + Row() { + Text('Custom Popup with transitionEffect').fontSize(10) + }.height(50).padding(5) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + + // PopupOptions 类型设置弹框内容 + Button('PopupOptions') + .margin({ top: 250 }) + .onClick(() => { + this.handlePopup = !this.handlePopup; + }) + .bindPopup(this.handlePopup, { + message: 'This is a popup with transitionEffect', + placementOnTop: true, + showInSubWindow: false, + onStateChange: (e) => { + if (!e.isVisible) { + this.handlePopup = false; + } + }, + // 设置弹窗显示动效为透明度动效与平移动效的组合效果,无退出动效 + transition:TransitionEffect.asymmetric( + TransitionEffect.OPACITY.animation({ duration: 1000, curve: Curve.Ease }).combine( + TransitionEffect.translate({ x: 50, y: 50 })), + TransitionEffect.IDENTITY) + }) + + + // CustomPopupOptions 类型设置弹框内容 + Button('CustomPopupOptions') + .margin({ top: 60 }) + .onClick(() => { + this.customPopup = !this.customPopup; + }) + .bindPopup(this.customPopup, { + builder: this.popupBuilder, + placement: Placement.Top, + showInSubWindow: false, + onStateChange: (e) => { + if (!e.isVisible) { + this.customPopup = false; + } + }, + // 设置弹窗显示动效与退出动效为缩放动效 + transition:TransitionEffect.scale({ x: 1, y: 0 }).animation({ duration: 500, curve: Curve.Ease }) + }) + + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.AnimationPopup_title')) + } +} +// [End animation_popup] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupStateChange.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupStateChange.ets new file mode 100644 index 0000000000000000000000000000000000000000..a9fc84f9844ebac1f5f2c79e7ef5b8336be22a42 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupStateChange.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 state_popup] +@Entry +@Component +export struct StatePopupExample { + @State handlePopup: boolean = false; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('PopupOptions') + .margin({ top: 300 }) + .onClick(() => { + this.handlePopup = !this.handlePopup; + }) + .bindPopup(this.handlePopup, { + message: 'This is a popup with PopupOptions', + onStateChange: (e)=> { // 返回当前的气泡状态 + if (!e.isVisible) { + this.handlePopup = false; + } + } + }) + }.width('100%').padding({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.onStateChange_title')) + } +} +// [End state_popup] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupStyle.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupStyle.ets new file mode 100644 index 0000000000000000000000000000000000000000..32426e33258fcf5b3976588d19b7bd58eaac91de --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/PopupStyle.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. + */ + +// [Start style_popup] +@Entry +@Component +export struct StylePopupExample { + @State handlePopup: boolean = false; + + // popup构造器定义弹框内容 + @Builder + popupBuilder() { + Row({ space: 2 }) { + Image($r('app.media.app_icon')).width(24).height(24).margin({ left: 5 }) + Text('This is Custom Popup').fontSize(15) + }.width(200).height(50).padding(5) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 100 }) { + Button('PopupOptions') + .margin({ top: 300 }) + .onClick(() => { + this.handlePopup = !this.handlePopup; + }) + .bindPopup(this.handlePopup, { + width: 200, + message: 'This is a popup.', + popupColor: Color.Pink, // 设置气泡的背景色 + mask: { + color: '#33d9d9d9' + }, + placement: Placement.Top, + backgroundBlurStyle: BlurStyle.NONE // 去除背景模糊效果需要关闭气泡的模糊背景 + }) + } + .width('100%') + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.StylePopup_title')) + } +} +// [End style_popup] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/TextPrompts.ets b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/TextPrompts.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ff872db5c2306411b3e34fabc9154d8771fc316 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/ets/pages/popup/TextPrompts.ets @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start text_popup] +@Entry +@Component +export struct TextPopupExample { + @State handlePopup: boolean = false; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('PopupOptions') + .margin({ top: 300 }) + .onClick(() => { + this.handlePopup = !this.handlePopup; + }) + .bindPopup(this.handlePopup, { + message: 'This is a popup with PopupOptions', + }) + }.width('100%').padding({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.TextPopup_title')) + } +} +// [End text_popup] \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/module.json5 b/ArkUISample/DialogProject/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4144486d1af4c03b0d767cce1cda86fc0d697f91 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/module.json5 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/resources/base/element/color.json b/ArkUISample/DialogProject/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/main/resources/base/element/string.json b/ArkUISample/DialogProject/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..e8029f5d16646d4405a24179a56d49258fd0b60b --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/resources/base/element/string.json @@ -0,0 +1,380 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "DialogProject" + }, + { + "name": "CustomDialog_dialog", + "value": "自定义弹窗" + }, + { + "name": "CustomDialog_create", + "value": "创建自定义弹框" + }, + { + "name": "CustomDialog_Animation", + "value": "弹窗渐出动画预览" + }, + { + "name": "CustomDialog_Animation1", + "value": "弹出框动画" + }, + { + "name": "CustomDialog_interaction", + "value": "弹出框交互" + }, + { + "name": "CustomDialog_interaction1", + "value": "弹出框交互页面跳转" + }, + { + "name": "CustomDialog_shadow", + "value": "弹窗设置边框阴影预览" + }, + { + "name": "CustomDialog_style", + "value": "弹出框的样式" + }, + { + "name": "CustomDialog_nest", + "value": "嵌套自定义弹出框" + }, + { + "name": "CustomDialog_create_des", + "value": "使用@CustomDialog装饰器装饰自定义弹出框,可在此装饰器内自定义弹出框内容。CustomDialogController需在@Component内定义。" + }, + { + "name": "CustomDialog_create_title", + "value": "创建自定义弹出框" + }, + { + "name": "CustomDialog_interaction_des", + "value": "弹出框可用于数据交互,完成用户一系列响应操作。" + }, + { + "name": "CustomDialog_interaction_title", + "value": "弹出框的交互" + }, + { + "name": "CustomDialog_interaction1_des", + "value": "可通过弹出框中的按钮实现路由跳转,同时获取跳转页面向当前页传入的参数。" + }, + { + "name": "CustomDialog_interaction1_title", + "value": "弹出框的交互页面跳转" + }, + { + "name": "CustomDialog_animation_des", + "value": "弹出框通过定义openAnimation控制弹出框出现动画的持续时间,速度等参数。" + }, + { + "name": "CustomDialog_animation_title", + "value": "弹出框的动画" + }, + { + "name": "CustomDialog_Style_des", + "value": "弹出框通过定义宽度、高度、背景色、阴影等参数来控制样式。" + }, + { + "name": "CustomDialog_Style_title", + "value": "弹出框的样式" + }, + { + "name": "CustomDialog_nest_des", + "value": "弹出框通过定义宽度、高度、背景色、阴影等参数来控制样式。" + }, + { + "name": "CustomDialog_nest_title", + "value": "弹出框的样式" + }, + { + "name": "CustomDialog_ActionSheet", + "value": "列表选择弹窗" + }, + { + "name": "CustomDialog_AlertDialog", + "value": "警告弹窗" + }, + { + "name": "CustomDialog_calender", + "value": "日历选择器弹窗" + }, + { + "name": "CustomDialog_date", + "value": "日期滑动选择器弹窗" + }, + { + "name": "CustomDialog_text", + "value": "文本滑动选择器弹窗" + }, + { + "name": "CustomDialog_time", + "value": "时间滑动选择器弹窗" + }, + { + "name": "CalendarPickerDialog_title", + "value": "日历选择器弹窗" + }, + { + "name": "CalendarPickerDialog_des", + "value": "日历选择器弹窗提供日历视图,包含年、月和星期信息,通过CalendarPickerDialog接口实现。开发者可调用show函数,定义并弹出日历选择器弹窗。" + }, + { + "name": "DatePicker_title", + "value": "日期滑动选择器弹窗" + }, + { + "name": "DatePicker_des", + "value": "开发者可以利用指定的日期范围,创建日期滑动选择器弹窗,将日期信息清晰地展示在弹出的窗口上。" + }, + { + "name": "TimePicker_title", + "value": "时间滑动选择器弹窗" + }, + { + "name": "TimePicker_des", + "value": "开发者可根据24小时的时间区间,创建时间滑动选择器弹窗,将时间信息清晰地展示在弹出的窗口上。" + }, + { + "name": "TextPicker_title", + "value": "文本滑动选择器弹窗" + }, + { + "name": "TextPicker_des", + "value": "开发者可根据指定的选择范围,创建文本滑动选择器弹窗,将文本信息清晰地展示在弹出的窗口上。" + }, + { + "name": "ActionSheet_title", + "value": "列表选择弹窗" + }, + { + "name": "ActionSheet_des", + "value": "列表选择器弹窗适用于呈现多个操作选项,尤其当界面中仅需展示操作列表而无其他内容时。" + }, + { + "name": "AlertDialog_title", + "value": "警告弹窗" + }, + { + "name": "AlertDialog_des", + "value": "需要向用户提问或得到用户的许可时,可使用警告弹窗。" + }, + { + "name": "fixed_dialog", + "value": "固定样式弹出框" + }, + { + "name": "menu_single", + "value": "菜单选项单级" + }, + { + "name": "menu_forbid", + "value": "菜单不可选择" + }, + { + "name": "menu_more", + "value": "菜单选项多级" + }, + { + "name": "menu_subtitle", + "value": "小标题" + }, + { + "name": "menu_selection", + "value": "菜单选项" + }, + { + "name": "menu_default", + "value": "默认样式" + }, + { + "name": "menu_bind", + "value": "属性绑定" + }, + { + "name": "menu_rightClick", + "value": "支持鼠标右键的菜单" + }, + { + "name": "create_menu", + "value": "创建菜单" + }, + { + "name": "menu", + "value": "菜单" + }, + { + "name": "CreateMenu_title", + "value": "创建自定义样式的菜单" + }, + { + "name": "CreateMenu_des", + "value": "菜单需要调用bindMenu接口来实现。bindMenu响应绑定组件的点击事件,绑定组件后手势点击对应组件后即可弹出。" + }, + { + "name": "Customdialog_title", + "value": "不依赖UI组件的全局自定义弹出框" + }, + { + "name": "Customdialog_des", + "value": "由于CustomDialogController在使用上存在诸多限制,不支持动态创建也不支持动态刷新,在相对较复杂的应用场景中推荐使用UIContext中获取到的PromptAction对象提供的openCustomDialog接口来实现自定义弹出框。" + }, + { + "name": "close_dialog", + "value": "关闭弹窗" + }, + { + "name": "change_dialog", + "value": "改变弹窗位置" + }, + { + "name": "change_text", + "value": "该按钮呼出的弹窗,点击“改变弹窗位置”弹窗由上对齐更新为底部对齐" + }, + { + "name": "open_customDialog", + "value": "不依赖UI组件的全局自定义弹出框" + }, + { + "name": "button_popup", + "value": "带按钮的提示气泡" + }, + { + "name": "custom_popup", + "value": "自定义气泡" + }, + { + "name": "popup", + "value": "气泡提示" + }, + { + "name": "TextPopup_title", + "value": "文本提示气泡" + }, + { + "name": "TextPopup_des", + "value": "文本提示气泡常用于只展示带有文本的信息提示,不带有任何交互的场景。Popup属性需绑定组件,当bindPopup属性中参数show为true时会弹出气泡提示。" + }, + { + "name": "onStateChange_title", + "value": "添加气泡状态变化的事件" + }, + { + "name": "onStateChange_des", + "value": "通过onStateChange参数为气泡添加状态变化的事件回调,可以判断当前气泡的显示状态。" + }, + { + "name": "ButtonPopup_title", + "value": "带按钮的提示气泡" + }, + { + "name": "ButtonPopup_des", + "value": "通过primaryButton、secondaryButton属性为气泡最多设置两个Button按钮,通过此按钮进行简单的交互,开发者可以通过配置action参数来设置想要触发的操作。" + }, + { + "name": "AnimationPopup_title", + "value": "气泡的动画" + }, + { + "name": "AnimationPopup_des", + "value": "气泡通过定义transition控制气泡的进场和出场动画效果。" + }, + { + "name": "CustomPopup_title", + "value": "自定义气泡" + }, + { + "name": "CustomPopup_des", + "value": "开发者可以使用CustomPopupOptions的builder创建自定义气泡,@Builder中可以放自定义的内容。除此之外,还可以通过popupColor等参数控制气泡样式。" + }, + { + "name": "StylePopup_title", + "value": "气泡样式" + }, + { + "name": "StylePopup_des", + "value": "气泡除了可以通过builder实现自定义气泡,还可以通过接口设置气泡的样式和显示效果。" + }, + { + "name": "toast", + "value": "即时反馈" + }, + { + "name": "CreateToast_title", + "value": "创建即时反馈" + }, + { + "name": "CreateToast_des", + "value": "适用于短时间内提示框自动消失的场景。" + }, + { + "name": "OpenCloseToast_title", + "value": "显示关闭即时反馈" + }, + { + "name": "OpenCloseToast_des", + "value": "适用于提示框提留时间较长,用户操作可以提前关闭提示框的场景。" + }, + { + "name": "openCustomDialog", + "value": "自定义弹出框/openCustomDialog" + }, + { + "name": "CustomDialog1", + "value": "基础自定义弹出框/CustomDialog" + }, + { + "name": "FixedStyleDialog1", + "value": "固定样式弹出框/FixedStyleDialog" + }, + { + "name": "Menu1", + "value": "菜单控制/Menu" + }, + { + "name": "Toast1", + "value": "即时反馈/Toast" + }, + { + "name": "Popup1", + "value": "气泡提示/Popup" + }, + { + "name": "back", + "value": "点击返回" + }, + { + "name": "ShowActionMenu_title", + "value": "操作菜单" + }, + { + "name": "ShowActionMenu_des", + "value": "操作菜单通过UIContext中的getPromptAction方法获取到PromptAction对象,再通过该对象调用showActionMenu接口实现,支持在回调或开发者自定义类中使用。" + }, + { + "name": "ShowDialog_title", + "value": "对话框" + }, + { + "name": "ShowDialog_des", + "value": "对话框通过UIContext中的getPromptAction方法获取到PromptAction对象,再通过该对象调用showDialog接口实现,支持在回调或开发者自定义类中使用。" + }, + { + "name": "DefaultAndTopToast_title", + "value": "即时反馈模式对比" + }, + { + "name": "DefaultAndTopToast_des", + "value": "即时反馈提供了两种显示模式,分别为DEFAULT(显示在应用内)、TOP_MOST(显示在应用之上)。" + } + ] +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/resources/base/media/background.png b/ArkUISample/DialogProject/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ArkUISample/DialogProject/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUISample/DialogProject/entry/src/main/resources/base/media/foreground.png b/ArkUISample/DialogProject/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ArkUISample/DialogProject/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUISample/DialogProject/entry/src/main/resources/base/media/layered_image.json b/ArkUISample/DialogProject/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/main/resources/base/media/startIcon.png b/ArkUISample/DialogProject/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUISample/DialogProject/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUISample/DialogProject/entry/src/main/resources/base/profile/backup_config.json b/ArkUISample/DialogProject/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/main/resources/base/profile/main_pages.json b/ArkUISample/DialogProject/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..f9a6423252cdb1b3afbc0a80bb3f9eda611228e7 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,6 @@ +{ + "src": [ + "pages/Index", + "pages/Index2" + ] +} diff --git a/ArkUISample/DialogProject/entry/src/main/resources/dark/element/color.json b/ArkUISample/DialogProject/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/Index.test.ets b/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..ed9b967625d9393f2ccf906fa1e7ee4853759e15 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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'; +// 导入测试依赖kit +import { abilityDelegatorRegistry, Driver, ON, MouseButton, Component, MatchPattern } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import resource from '../../../main/ets/common/resource'; + + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator() +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + +function sleep(time: number) { + return new Promise((resolve: Function) => setTimeout(resolve, time)); +} + + +export default function IndexTest() { + + describe('IndexTest', () => { + + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + await sleep(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info("get top ability"); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + it('testOpenCustomDialog', 0, async (done: Function) => { + console.info("uitest: testOpenCustomDialog begin"); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text('openCustomDialog', MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text('UI', MatchPattern.CONTAINS)); + await button_list1.click(); + let button1 = await driver.findComponent(ON.id('open')); + await button1.click(); + + let button2 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.change_dialog')), MatchPattern.CONTAINS)); + await button2.click(); + await sleep(1000); + await driver.pressBack(); + await driver.pressBack(); + await driver.pressBack(); + done(); + }) + + it('testCustomDialog', 0, async (done: Function) => { + console.info("uitest: testCustomDialog begin"); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.CustomDialog1')), MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.CustomDialog_nest')), MatchPattern.CONTAINS)); + await button_list1.click(); + + let button_list2 = await driver.findComponent(ON.text('Click', MatchPattern.CONTAINS)); + await button_list2.click(); + let button_list3 = await driver.findComponent(ON.text('confirm', MatchPattern.CONTAINS)); + await button_list3.click(); + let button_list4 = await driver.findComponent(ON.text('close', MatchPattern.CONTAINS)); + await button_list4.click(); + await driver.pressBack(); + await driver.pressBack(); + await sleep(1000); + done(); + }) + + it('testFixedCustomDialog', 0, async (done: Function) => { + console.info("uitest: testFixedCustomDialog begin"); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.FixedStyleDialog1')), MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.DatePicker_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + + let button_list2 = await driver.findComponent(ON.text('showDate', MatchPattern.CONTAINS)); + await button_list2.click(); + await driver.pressBack(); + await driver.pressBack(); + await driver.pressBack(); + await sleep(1000); + done(); + }) + + it('testMenu', 0, async (done: Function) => { + console.info("uitest: testMenu begin"); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.Menu1')), MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.CreateMenu_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + + let button_list2 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.menu_bind')), MatchPattern.CONTAINS)); + await button_list2.click(); + await driver.pressBack(); + await driver.pressBack(); + await driver.pressBack(); + await driver.pressBack(); + await sleep(1000); + done(); + }) + + it('testToast', 0, async (done: Function) => { + console.info("uitest: testToast begin"); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.Toast1')), MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.OpenCloseToast_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + + let button1 = await driver.findComponent(ON.text('Open', MatchPattern.CONTAINS)); + await button1.click(); + let button2 = await driver.findComponent(ON.text('Close', MatchPattern.CONTAINS)); + await button2.click(); + await driver.pressBack(); + await driver.pressBack(); + await driver.pressBack(); + await sleep(1000); + done(); + }) + + + }) +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/List.test.ets b/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..3d739bce6f4114150b415adb0cef32e93643f243 --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import IndexTest from './Index.test' +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); + IndexTest() +} \ No newline at end of file diff --git a/ArkUISample/DialogProject/entry/src/ohosTest/module.json5 b/ArkUISample/DialogProject/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4c262abdf023b2ec4a9333c029b0b544d561a77d --- /dev/null +++ b/ArkUISample/DialogProject/entry/src/ohosTest/module.json5 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUISample/DialogProject/hvigor/hvigor-config.json5 b/ArkUISample/DialogProject/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/hvigorfile.ts b/ArkUISample/DialogProject/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/ArkUISample/DialogProject/hvigorfile.ts @@ -0,0 +1,6 @@ +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/ArkUISample/DialogProject/oh-package.json5 b/ArkUISample/DialogProject/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/ArkUISample/DialogProject/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/ArkUISample/DialogProject/screenshots/device/image1.png b/ArkUISample/DialogProject/screenshots/device/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..ed562c1aa1a2832b992c851eb175c2f109d117aa Binary files /dev/null and b/ArkUISample/DialogProject/screenshots/device/image1.png differ diff --git a/ArkUISample/DialogProject/screenshots/device/image2.png b/ArkUISample/DialogProject/screenshots/device/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..26fce1fb323a91ccd6d51a552bda47287b450c73 Binary files /dev/null and b/ArkUISample/DialogProject/screenshots/device/image2.png differ diff --git a/ArkUISample/DialogProject/screenshots/device/image3.png b/ArkUISample/DialogProject/screenshots/device/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..7ae66b6f447d682fe83ec96085a99fb2a23d0b90 Binary files /dev/null and b/ArkUISample/DialogProject/screenshots/device/image3.png differ diff --git a/ArkUISample/EventProject/.gitignore b/ArkUISample/EventProject/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ArkUISample/EventProject/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/ArkUISample/EventProject/AppScope/app.json5 b/ArkUISample/EventProject/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a3ecaff149f0fe344f8c8144d5dad0b39b76c81a --- /dev/null +++ b/ArkUISample/EventProject/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.eventproject", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ArkUISample/EventProject/AppScope/resources/base/element/string.json b/ArkUISample/EventProject/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..583c3a07c4c83a1afdf5508acb97c1bc2519d3df --- /dev/null +++ b/ArkUISample/EventProject/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "EventProject" + } + ] +} diff --git a/ArkUISample/EventProject/AppScope/resources/base/media/app_icon.png b/ArkUISample/EventProject/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ArkUISample/EventProject/AppScope/resources/base/media/app_icon.png differ diff --git a/ArkUISample/EventProject/README_zh.md b/ArkUISample/EventProject/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..48c486c825a5f31188716bf39a91904e9a1affb9 --- /dev/null +++ b/ArkUISample/EventProject/README_zh.md @@ -0,0 +1,111 @@ +# ArkUI使用支持交互事件指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [触屏事件](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-common-events-touch-screen-event.md) +2. [键鼠事件](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-common-events-device-input-event.md) +3. [焦点事件](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-common-events-focus-event.md) +4. [拖拽事件](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-common-events-drag-event.md) +5. [单一手势](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-gesture-events-single-gesture.md) +6. [组合手势](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-gesture-events-combined-gestures.md) +7. [手势拦截](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-gesture-events-gesture-judge.md) +### 效果预览 + +| 首页 | 交互类组件目录 | 单一手势示例 | +|------------------------------------|------------------------------------|------------------------------------| +| ![](screenshots/device/image1.png) | ![](screenshots/device/image2.png) | ![](screenshots/device/image3.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +|---pages +| |---device //键鼠事件 +| | |---HoverEffect.ets +| | |---OnHover.ets +| | |---OnKey.ets +| | |---OnKeyPreIme.ets +| | |---OnMouse.ets +| | |---Index.ets +| |---focus //焦点事件 +| | |---DefaultFocus.ets +| | |---Focusable.ets +| | |---FocusAndClick.ets +| | |---FocusController.ets +| | |---Index.ets +| | |---FocusPriority.ets +| | |---FocusScopePriority.ets +| | |---FocusStyle.ets +| | |---onFocusBlur.ets +| |---drag //拖拽事件 +| | |---DefaultDrag.ets +| | |---Index.ets +| | |---MoreDrag.ets +| |---gesturejudge //手势拦截 +| | |---Index.ets +| | |---GestureJudge.ets +| |---singlegesture //单一手势 +| | |---LongPressGesture.ets +| | |---PanGesture.ets +| | |---Index.ets +| | |---PinchGesture.ets +| | |---RotationGesture.ets +| | |---SwipeGesture.ets +| | |---TapGesture.ets +| |---Touch //触屏事件 +| | |---ClickEvent.ets +| | |---Index.ets +| | |---TouchEvent.ets +| |---groupgesture //组合手势 +| | |---Exclusive.ets +| | |---Index.ets +| | |---Parallel.ets +| | |---Sequence.ets +|---pages +| |---Index.ets // 应用主页面 +entry/src/ohosTest/ +|---ets +| |---index.test.ets // 示例代码测试代码 +``` + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo ArkUISample/EventProject > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/ArkUISample/EventProject/build-profile.json5 b/ArkUISample/EventProject/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..dfff6457ac81a00849902e6cc61886b8d9312f15 --- /dev/null +++ b/ArkUISample/EventProject/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.2(14)", + "targetSdkVersion": "5.0.2(14)", + "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/ArkUISample/EventProject/code-linter.json5 b/ArkUISample/EventProject/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/.gitignore b/ArkUISample/EventProject/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ArkUISample/EventProject/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/build-profile.json5 b/ArkUISample/EventProject/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ArkUISample/EventProject/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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": { + }, + "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/ArkUISample/EventProject/entry/hvigorfile.ts b/ArkUISample/EventProject/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ArkUISample/EventProject/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +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/ArkUISample/EventProject/entry/obfuscation-rules.txt b/ArkUISample/EventProject/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/oh-package.json5 b/ArkUISample/EventProject/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUISample/EventProject/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUISample/EventProject/entry/src/main/ets/common/Card.ets b/ArkUISample/EventProject/entry/src/main/ets/common/Card.ets new file mode 100644 index 0000000000000000000000000000000000000000..bbddb561a11098edf02e511d49b373ab40446a79 --- /dev/null +++ b/ArkUISample/EventProject/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: string; + + 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/ArkUISample/EventProject/entry/src/main/ets/common/Route.ets b/ArkUISample/EventProject/entry/src/main/ets/common/Route.ets new file mode 100644 index 0000000000000000000000000000000000000000..a74522e3505237cb50822114c4aab7086b35253e --- /dev/null +++ b/ArkUISample/EventProject/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?: string; +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/common/resource.ets b/ArkUISample/EventProject/entry/src/main/ets/common/resource.ets new file mode 100644 index 0000000000000000000000000000000000000000..f0adea122eb448c7ec79abe18b76f532278a1704 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUISample/EventProject/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..edc2839f203ba057c186e19b0cbbbf80c8faa8b3 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUISample/EventProject/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -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. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..03155cfdd0550b0355d8db6dce4e09007ef4c83f --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { LengthMetrics } from '@kit.ArkUI'; +import { RoutableCard } from '../common/Card'; +import { Route } from '../common/Route'; +import { DeviceDestination, Device_ROUTE_PREFIX } from './device/Index'; +import { DragGestureDestination, Drag_ROUTE_PREFIX } from './drag/Index'; +import { FocusDestination, Focus_ROUTE_PREFIX } from './focus/Index'; +import { GestureJudgeDestination, GestureJudge_ROUTE_PREFIX } from './gesturejudge/Index'; +import { GroupGestureDestination, GroupGesture_ROUTE_PREFIX } from './groupgesture/Index'; +import { Gesture_ROUTE_PREFIX, GestureDestination } from './singlegesture/Index'; +import { TouchDestination, Touch_ROUTE_PREFIX } from './Touch/Index'; +import resource from '../common/resource'; + +const routes: Route[] = [ + { + title: resource.resourceToString($r('app.string.Pages_Index_gesture')), + name: Gesture_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Pages_Index_GroupGesture')), + name: GroupGesture_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Pages_Index_GestureJudge')), + name: GestureJudge_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Pages_Index_TouchEvent')), + name: Touch_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Pages_Index_DeviceEvent')), + name: Device_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Pages_Index_FocusEvent')), + name: Focus_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.Pages_Index_DragEvent')), + name: Drag_ROUTE_PREFIX + } +]; + +@Builder +function Destination(name: string) { + if (name.startsWith(Gesture_ROUTE_PREFIX)) { + GestureDestination(name); + } else if (name.startsWith(GroupGesture_ROUTE_PREFIX)) { + GroupGestureDestination(name); + } else if (name.startsWith(GestureJudge_ROUTE_PREFIX)) { + GestureJudgeDestination(name); + } else if (name.startsWith(Touch_ROUTE_PREFIX)) { + TouchDestination(name); + } else if (name.startsWith(Device_ROUTE_PREFIX)) { + DeviceDestination(name); + } else if (name.startsWith(Focus_ROUTE_PREFIX)) { + FocusDestination(name); + } else if (name.startsWith(Drag_ROUTE_PREFIX)) { + DragGestureDestination(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() { + 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) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/ClickEvent.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/ClickEvent.ets new file mode 100644 index 0000000000000000000000000000000000000000..84555db100b8e1c1ad81f4dc1be3f189d24286d5 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/ClickEvent.ets @@ -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. + */ + +// [Start click_event_handle] +@Entry +@Component +export struct Click { + @State flag: boolean = true; + @State btnMsg: string = 'show'; + + build() { + NavDestination() { + Column({ space: 12 }) { + Text($r('app.string.Touch_ClickEvent_text')) + .fontSize(14) + .fontColor('#666') + Column() { + Button(this.btnMsg).width(80).height(30).margin(30) + .onClick(() => { + if (this.flag) { + this.btnMsg = 'hide'; + } else { + this.btnMsg = 'show'; + } + // 点击Button控制Image的显示和消失 + this.flag = !this.flag; + }) + if (this.flag) { + Image($r('app.media.app_icon')).width(200).height(200) + } + }.height('100%').width('100%') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Touch_ClickEvent_title')) + } +} +// [End click_event_handle] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..4830e9f24dd8d7ed12b3532d284dfbd71e01e400 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/Index.ets @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { Click } from './ClickEvent'; +import { Touch } from './TouchEvent'; +import resource from '../../common/resource'; + +export const Touch_ROUTE_PREFIX: string = 'Touch_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Touch_ROUTE_PREFIX}/ClickEvent`, + title: resource.resourceToString($r('app.string.Touch_Index_ClickEvent_title')), + description: resource.resourceToString($r('app.string.Touch_Index_ClickEvent_description')) + }, + { + name: `${Touch_ROUTE_PREFIX}/TouchEvent`, + title: resource.resourceToString($r('app.string.Touch_Index_TouchEvent_title')), + description: resource.resourceToString($r('app.string.Touch_Index_TouchEvent_description')), + } +] + +@Builder +export function TouchDestination(name: string) { + if (name === Touch_ROUTE_PREFIX) { + TouchExample(); + } else if (name === routes[0].name) { + Click(); + } else if (name === routes[1].name) { + Touch(); + } +} + +@Entry +@Component +struct TouchExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.Touch_Index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/TouchEvent.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/TouchEvent.ets new file mode 100644 index 0000000000000000000000000000000000000000..d423f073d40410c426dba4ca19877c7c52290f7c --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/Touch/TouchEvent.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 touch_event_handle] +@Entry +@Component +export struct Touch { + @State text: string = ''; + @State eventType: string = ''; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('Touch').height(40).width(100) + .onTouch((event?: TouchEvent) => { + if (event) { + if (event.type === TouchType.Down) { + this.eventType = 'Down'; + } + if (event.type === TouchType.Up) { + this.eventType = 'Up'; + } + if (event.type === TouchType.Move) { + this.eventType = 'Move'; + } + this.text = 'TouchType:' + this.eventType + '\nDistance between touch point and touch element:\nx: ' + + event.touches[0].x + '\n' + 'y: ' + event.touches[0].y + '\nComponent globalPos:(' + + event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:' + + event.target.area.width + '\nheight:' + event.target.area.height + } + }) + Button('Touch').height(50).width(200).margin(20) + .onTouch((event?: TouchEvent) => { + if (event) { + if (event.type === TouchType.Down) { + this.eventType = 'Down'; + } + if (event.type === TouchType.Up) { + this.eventType = 'Up'; + } + if (event.type === TouchType.Move) { + this.eventType = 'Move'; + } + this.text = 'TouchType:' + this.eventType + '\nDistance between touch point and touch element:\nx: ' + + event.touches[0].x + '\n' + 'y: ' + event.touches[0].y + '\nComponent globalPos:(' + + event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:' + + event.target.area.width + '\nheight:' + event.target.area.height + } + }) + Text(this.text) + }.width('100%').padding(30) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Touch_TouchEvent_title')) + } +} +// [End touch_event_handle] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/device/HoverEffect.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/device/HoverEffect.ets new file mode 100644 index 0000000000000000000000000000000000000000..198de86e063fb71801303866048a561921b6471d --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/device/HoverEffect.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 mouse_hover_effect] +@Entry +@Component +export struct HoverEffectSample { + @State buttonText: string = ''; + @State columnText: string = ''; + @State hoverText: string = 'Not Hover'; + @State color: Color = Color.Gray; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 10 }) { + Button('Auto') + .width(170).height(70) + Button('Scale') + .width(170).height(70) + .hoverEffect(HoverEffect.Scale) + Button('Highlight') + .width(170).height(70) + .hoverEffect(HoverEffect.Highlight) + Button('None') + .width(170).height(70) + .hoverEffect(HoverEffect.None) + }.width('100%').height('100%').justifyContent(FlexAlign.Center) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.HoverEffectSample_title')) + } +} +// [End mouse_hover_effect] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/device/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/device/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..6038ec2267fca219997bff1163c71c8253b04d6d --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/device/Index.ets @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { HoverEffectSample } from './HoverEffect'; +import { Hover } from './OnHover'; +import { OnKey } from './OnKey'; +import { PreIme } from './OnKeyPreIme'; +import { Mouse } from './OnMouse'; +import resource from '../../common/resource'; + + +export const Device_ROUTE_PREFIX: string = 'Device_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Device_ROUTE_PREFIX}/OnHover`, + title: resource.resourceToString($r('app.string.Hover_Event')), + description: resource.resourceToString($r('app.string.Hover_Description')), + }, + { + name: `${Device_ROUTE_PREFIX}/OnMouse`, + title: resource.resourceToString($r('app.string.Mouse_Event')), + description: resource.resourceToString($r('app.string.Mouse_Description')) + }, + { + name: `${Device_ROUTE_PREFIX}/HoverEffect`, + title: resource.resourceToString($r('app.string.Hover_Effect')), + description: resource.resourceToString($r('app.string.Hover_Effect_Description')), + }, + { + name: `${Device_ROUTE_PREFIX}/onKeyEvent `, + title: resource.resourceToString($r('app.string.Key_Event')), + description: resource.resourceToString($r('app.string.Key_Description')), + }, + { + name: `${Device_ROUTE_PREFIX}/OnKeyPreIme `, + title: resource.resourceToString($r('app.string.Key_PreIme')), + description: resource.resourceToString($r('app.string.Key_PreIme_Description')), + } + + +] + +@Builder +export function DeviceDestination(name: string) { + if (name === Device_ROUTE_PREFIX) { + DeviceExample(); + } else if (name === routes[0].name) { + Hover(); + } else if (name === routes[1].name) { + Mouse(); + } else if (name === routes[2].name) { + HoverEffectSample(); + } else if (name === routes[3].name) { + OnKey(); + } else if (name === routes[4].name) { + PreIme(); + } +} + +@Entry +@Component +struct DeviceExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.Device_index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnHover.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnHover.ets new file mode 100644 index 0000000000000000000000000000000000000000..6992c005cee95ca32fa5a6fffdd837e37af9470c --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnHover.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 dynamic_response_mouse_hover] +@Entry +@Component +export struct Hover { + @State hoverText: string = 'Not Hover'; + @State color: Color = Color.Gray; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button(this.hoverText) + .width(200).height(100) + .backgroundColor(this.color) + .onHover((isHover?: boolean) => { // 使用onHover接口监听鼠标是否悬浮在Button组件上 + if (isHover) { + this.hoverText = 'Hovered!'; + this.color = Color.Green; + } else { + this.hoverText = 'Not Hover'; + this.color = Color.Gray; + } + }) + }.width('100%').height('100%').justifyContent(FlexAlign.Center) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Device_OnHover_title')) + } +} +// [End dynamic_response_mouse_hover] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnKey.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnKey.ets new file mode 100644 index 0000000000000000000000000000000000000000..eaa8bc571e56996e40634da472ab23320ec88691 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnKey.ets @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 listen_response_key_event] +@Entry +@Component +export struct OnKey { + @State buttonText: string = ''; + @State buttonType: string = ''; + @State columnText: string = ''; + @State columnType: string = ''; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button('onKeyEvent') + .defaultFocus(true) + .width(140).height(70) + .onKeyEvent((event?: KeyEvent) => { // 给Button设置onKeyEvent事件 + if(event){ + if (event.type === KeyType.Down) { + this.buttonType = 'Down'; + } + if (event.type === KeyType.Up) { + this.buttonType = 'Up'; + } + this.buttonText = 'Button: \n' + + 'KeyType:' + this.buttonType + '\n' + + 'KeyCode:' + event.keyCode + '\n' + + 'KeyText:' + event.keyText; + } + }) + + Divider() + Text(this.buttonText).fontColor(Color.Green) + + Divider() + Text(this.columnText).fontColor(Color.Red) + }.width('100%').height('100%').justifyContent(FlexAlign.Center) + .onKeyEvent((event?: KeyEvent) => { // 给父组件Column设置onKeyEvent事件 + if(event){ + if (event.type === KeyType.Down) { + this.columnType = 'Down'; + } + if (event.type === KeyType.Up) { + this.columnType = 'Up'; + } + this.columnText = 'Column: \n' + + 'KeyType:' + this.buttonType + '\n' + + 'KeyCode:' + event.keyCode + '\n' + + 'KeyText:' + event.keyText; + } + }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Device_OnKey_title')) + } +} +// [End listen_response_key_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnKeyPreIme.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnKeyPreIme.ets new file mode 100644 index 0000000000000000000000000000000000000000..32edef1b979e0a2bcf6ad0dabc73691f2f26872b --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnKeyPreIme.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start key_event_intercept] +import { KeyCode } from '@kit.InputKit'; + +@Entry +@Component +export struct PreIme { + @State buttonText: string = ''; + @State buttonType: string = ''; + @State columnText: string = ''; + @State columnType: string = ''; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Search({ + placeholder: 'Search...' + }) + .width('80%') + .height('40vp') + .border({ radius:'20vp' }) + .onKeyPreIme((event:KeyEvent) => { + if (event.keyCode == KeyCode.KEYCODE_DPAD_LEFT) { + return true; + } + return false; + }) + } + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Device_OnKeyPreIme_title')) + } +} +// [End key_event_intercept] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnMouse.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnMouse.ets new file mode 100644 index 0000000000000000000000000000000000000000..baab41e24e74633e70a408537ae47d37aa2d4bcb --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/device/OnMouse.ets @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start listen_response_mouse_event] +@Entry +@Component +export struct Mouse { + @State buttonText: string = ''; + @State columnText: string = ''; + @State hoverText: string = 'Not Hover'; + @State color: Color = Color.Gray; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button(this.hoverText) + .width(200) + .height(100) + .backgroundColor(this.color) + .onHover((isHover?: boolean) => { + if (isHover) { + this.hoverText = 'Hovered!'; + this.color = Color.Green; + } else { + this.hoverText = 'Not Hover'; + this.color = Color.Gray; + } + }) + .onMouse((event?: MouseEvent) => { // 设置Button的onMouse回调 + if (event) { + this.buttonText = 'Button onMouse:\n' + '' + + 'button = ' + event.button + '\n' + + 'action = ' + event.action + '\n' + + 'x,y = (' + event.x + ',' + event.y + ')' + '\n' + + 'windowXY=(' + event.windowX + ',' + event.windowY + ')'; + } + }) + Divider() + Text(this.buttonText).fontColor(Color.Green) + Divider() + Text(this.columnText).fontColor(Color.Red) + } + .width('100%') + .height('100%') + .justifyContent(FlexAlign.Center) + .borderWidth(2) + .borderColor(Color.Red) + .onMouse((event?: MouseEvent) => { // Set the onMouse callback for the column. + if (event) { + this.columnText = 'Column onMouse:\n' + '' + + 'button = ' + event.button + '\n' + + 'action = ' + event.action + '\n' + + 'x,y = (' + event.x + ',' + event.y + ')' + '\n' + + 'windowXY=(' + event.windowX + ',' + event.windowY + ')'; + } + }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Device_OnMouse_title')) + } +} +// [End listen_response_mouse_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/drag/DefaultDrag.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/drag/DefaultDrag.ets new file mode 100644 index 0000000000000000000000000000000000000000..ad23de3c804ceb7331bb8b71d5a8a0463ed1caf7 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/drag/DefaultDrag.ets @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 default_drag] +import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData'; +import { promptAction } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { image } from '@kit.ImageKit'; + +@Entry +@Component +export struct DefaultDrag { + @State targetImage: string = ''; + @State imageWidth: number = 100; + @State imageHeight: number = 100; + @State imgState: Visibility = Visibility.Visible; + @State pixmap: image.PixelMap | undefined = undefined; + + // [Start generate_pix_map] + @Builder + pixelMapBuilder() { + Column() { + Image($r('app.media.startIcon')) + .width(120) + .height(120) + .backgroundColor(Color.Yellow) + } + } + + // [StartExclude generate_pix_map] + // [Start data_delayed_retry] + getDataFromUdmfRetry(event: DragEvent, callback: (data: DragEvent) => void) { + try { + let data: UnifiedData = event.getData(); + if (!data) { + return false; + } + let records: unifiedDataChannel.UnifiedRecord[] = data.getRecords(); + if (!records || records.length <= 0) { + return false; + } + callback(event); + return true; + } catch (e) { + console.log('getData failed, code: ' + (e as BusinessError).code + ', message: ' + (e as BusinessError).message); + return false; + } + } + + // 获取UDMF数据,首次获取失败后添加1500ms延迟重试机制 + getDataFromUdmf(event: DragEvent, callback: (data: DragEvent) => void) { + if (this.getDataFromUdmfRetry(event, callback)) { + return; + } + setTimeout(() => { + this.getDataFromUdmfRetry(event, callback); + }, 1500); + } + // [End data_delayed_retry] + // [EndExclude generate_pix_map] + + // 调用componentSnapshot中的createFromBuilder接口截取自定义builder的截图 + private getComponentSnapshot(): void { + this.getUIContext().getComponentSnapshot().createFromBuilder(() => { + this.pixelMapBuilder() + }, + (error: Error, pixmap: image.PixelMap) => { + if (error) { + console.log('error: ' + JSON.stringify(error)); + return; + } + this.pixmap = pixmap; + }) + } + // [End generate_pix_map] + + // 长按50ms时提前准备自定义截图的pixmap + private PreDragChange(preDragStatus: PreDragStatus): void { + if (preDragStatus == PreDragStatus.ACTION_DETECTING_STATUS) { + this.getComponentSnapshot(); + } + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Row() { + Column() { + Text('start Drag') + .fontSize(18) + .width('100%') + .height(40) + .margin(10) + .backgroundColor('#008888') + Row() { + // [Start module_draggable] + Image($r('app.media.app_icon')) + .width(100) + .height(100) + .draggable(true) + .margin({ left: 15 }) + // [StartExclude module_draggable] + .visibility(this.imgState)// 绑定平行手势,可同时触发应用自定义长按手势 + // [Start bind_parallel_gesture] + .parallelGesture(LongPressGesture().onAction(() => { + promptAction.showToast({ duration: 100, message: 'Long press gesture trigger' }); + })) + // [End bind_parallel_gesture] + // [EndExclude module_draggable] + .onDragStart((event) => { + let data: unifiedDataChannel.Image = new unifiedDataChannel.Image(); + data.imageUri = 'common/pic/img.png'; + let unifiedData = new unifiedDataChannel.UnifiedData(data); + event.setData(unifiedData); + + let dragItemInfo: DragItemInfo = { + pixelMap: this.pixmap, + extraInfo: 'this is extraInfo', + }; + return dragItemInfo; + }) + // [End module_draggable] + // 提前准备拖拽自定义背板图 + // [Start set_custom_drag_status] + .onPreDrag((status: PreDragStatus) => { + this.PreDragChange(status); + }) + // [End set_custom_drag_status] + // [Start set_on_drag_end] + .onDragEnd((event) => { + // onDragEnd里取到的result值在接收方onDrop设置 + if (event.getResult() === DragResult.DRAG_SUCCESSFUL) { + promptAction.showToast({ duration: 100, message: 'Drag Success' }); + } else if (event.getResult() === DragResult.DRAG_FAILED) { + promptAction.showToast({ duration: 100, message: 'Drag failed' }); + } + }) + // [End set_on_drag_end] + } + + Text('Drag Target Area') + .fontSize(20) + .width('100%') + .height(40) + .margin(10) + .backgroundColor('#008888') + Row() { + Image(this.targetImage) + .width(this.imageWidth) + .height(this.imageHeight) + .draggable(true) + .margin({ left: 15 }) + .border({ color: Color.Black, width: 1 })// 控制角标显示类型为MOVE,即不显示角标 + // [Start set_drag_behavior_move] + .onDragMove((event) => { + event.setResult(DragResult.DROP_ENABLED) + event.dragBehavior = DragBehavior.MOVE + // [End set_drag_behavior_move] + }) + // [Start allow_drag_type] + .allowDrop([uniformTypeDescriptor.UniformDataType.IMAGE]) + // [End allow_drag_type] + // [Start set_on_drop_call] + .onDrop((dragEvent?: DragEvent) => { + // 获取拖拽数据 + this.getDataFromUdmf((dragEvent as DragEvent), (event: DragEvent) => { + let records: unifiedDataChannel.UnifiedRecord[] = event.getData().getRecords(); + let rect: Rectangle = event.getPreviewRect(); + this.imageWidth = Number(rect.width); + this.imageHeight = Number(rect.height); + this.targetImage = (records[0] as unifiedDataChannel.Image).imageUri; + this.imgState = Visibility.None; + // 显式设置result为successful,则将该值传递给拖出方的onDragEnd + event.setResult(DragResult.DRAG_SUCCESSFUL); + }) + }) + // [End set_on_drop_call] + } + } + .width('100%') + .height('100%') + } + .height('100%') + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Drag_DefaultDrag_title')) + } +} +// [End default_drag] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/drag/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/drag/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1794489965e80197e10579586d2887b64b77243 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/drag/Index.ets @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { DefaultDrag } from './DefaultDrag'; +import { MoreDrag } from './MoreDrag'; +import resource from '../../common/resource'; + +export const Drag_ROUTE_PREFIX: string = 'Drag_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Drag_ROUTE_PREFIX}/Defaultdrag`, + title: resource.resourceToString($r('app.string.Drag_Index_DefaultDrag_title')), + description: resource.resourceToString($r('app.string.Drag_Index_DefaultDrag_description')), + }, + { + name: `${Drag_ROUTE_PREFIX}/MoreDrag`, + title: resource.resourceToString($r('app.string.Drag_Index_MoreDrag_title')), + description: resource.resourceToString($r('app.string.Drag_Index_MoreDrag_description')), + } +] + +@Builder +export function DragGestureDestination(name: string) { + if (name === Drag_ROUTE_PREFIX) { + DragGestureExample(); + } else if (name === routes[0].name) { + DefaultDrag(); + } else if (name === routes[1].name) { + MoreDrag(); + } +} + +@Entry +@Component +struct DragGestureExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.Drag_Index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/drag/MoreDrag.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/drag/MoreDrag.ets new file mode 100644 index 0000000000000000000000000000000000000000..85b1a0ed9793fb3ec1f1585146043477cb2e6676 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/drag/MoreDrag.ets @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start more_drag] +import { KeyCode } from '@kit.InputKit'; +import { image } from '@kit.ImageKit'; + +@Entry +@Component +export struct MoreDrag { + @State pixmap: image.PixelMap | undefined = undefined; + @State numbers: number[] = []; + @State isSelectedGrid: boolean[] = []; + @State previewData: DragItemInfo[] = []; + @State colors: Color[] = + [Color.Red, Color.Blue, Color.Brown, Color.Gray, Color.Green, Color.Grey, Color.Orange, Color.Pink, Color.Yellow]; + @State numberBadge: number = 0; + + @Styles + normalStyles(): void { + .opacity(1.0); + } + + @Styles + selectStyles(): void { + .opacity(0.4); + } + + onPageShow(): void { + let i: number = 0 + for (i = 0; i < 100; i++) { + this.numbers.push(i); + this.isSelectedGrid.push(false); + this.previewData.push({}); + } + } + + @Builder + RandomBuilder(idx: number) { + Column() + .backgroundColor(this.colors[idx % 9]) + .width(50) + .height(50) + .opacity(1.0) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 5 }) { + // [Start create_grid_item_module] + Grid() { + ForEach(this.numbers, (idx: number) => { + GridItem() { + Column() + .backgroundColor(this.colors[idx % 9]) + .width(50) + .height(50) + .opacity(1.0) + .id('grid' + idx) + } + // [StartExclude create_grid_item_module] + .dragPreview(this.previewData[idx]) + .selectable(true) + .selected(this.isSelectedGrid[idx]) + // 设置多选显示效果 + .stateStyles({ + normal: this.normalStyles, + selected: this.selectStyles + }) + // [Start grid_item_module_selected_true] + .onClick(() => { + this.isSelectedGrid[idx] = !this.isSelectedGrid[idx]; + // [StartExclude grid_item_module_selected_true] + if (this.isSelectedGrid[idx]) { + this.numberBadge++; + let gridItemName = 'grid' + idx; + // 选中状态下提前调用componentSnapshot中的get接口获取pixmap + this.getUIContext() + .getComponentSnapshot() + .get(gridItemName, (error: Error, pixmap: image.PixelMap) => { + this.pixmap = pixmap; + this.previewData[idx] = { + pixelMap: this.pixmap + }; + }) + } else { + this.numberBadge--; + } + // [EndExclude grid_item_module_selected_true] + }) + // [End grid_item_module_selected_true] + // 使能多选拖拽,右上角数量角标需要应用设置numberBadge参数 + // [EndExclude create_grid_item_module] + // [Start drag_preview_options] + .dragPreviewOptions({ numberBadge: this.numberBadge }, + { isMultiSelectionEnabled: true, defaultAnimationBeforeLifting: true }) + // [End drag_preview_options] + .onDragStart(() => { + }) + }, (idx: string) => idx) + } + // [End create_grid_item_module] + .columnsTemplate('1fr 1fr 1fr 1fr 1fr') + .columnsGap(5) + .rowsGap(10) + .backgroundColor(0xFAEEE0) + }.width('100%').margin({ top: 5 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Drag_MoreDrag_title')) + } +} +// [End more_drag] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/DefaultFocus.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/DefaultFocus.ets new file mode 100644 index 0000000000000000000000000000000000000000..96fe7d74e62b4d7baefe941af59b78203e29ad20 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/DefaultFocus.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 { KeyCode } from '@kit.InputKit'; + +// [Start focus_visualization_manage] +@Entry +@Component +export struct DefaultFocus { + @State oneButtonColor: Color = Color.Gray; + @State twoButtonColor: Color = Color.Gray; + @State threeButtonColor: Color = Color.Gray; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 20 }) { + // 通过外接键盘的上下键可以让焦点在三个按钮间移动,按钮获焦时颜色变化,失焦时变回原背景色 + Button('First Button') + .width(260) + .height(70) + .backgroundColor(this.oneButtonColor) + .fontColor(Color.Black) + // 监听第一个组件的获焦事件,获焦后改变颜色 + .onFocus(() => { + this.oneButtonColor = Color.Green; + }) + // 监听第一个组件的失焦事件,失焦后改变颜色 + .onBlur(() => { + this.oneButtonColor = Color.Gray; + }) + + Button('Second Button') + .width(260) + .height(70) + .backgroundColor(this.twoButtonColor) + .fontColor(Color.Black) + // 监听第二个组件的获焦事件,获焦后改变颜色 + .onFocus(() => { + this.twoButtonColor = Color.Green; + }) + // 监听第二个组件的失焦事件,失焦后改变颜色 + .onBlur(() => { + this.twoButtonColor = Color.Grey; + }) + + Button('Third Button') + .width(260) + .height(70) + .backgroundColor(this.threeButtonColor) + .fontColor(Color.Black) + // 设置默认焦点 + .defaultFocus(true) + // 监听第三个组件的获焦事件,获焦后改变颜色 + .onFocus(() => { + this.threeButtonColor = Color.Green; + }) + // 监听第三个组件的失焦事件,失焦后改变颜色 + .onBlur(() => { + this.threeButtonColor = Color.Gray; + }) + }.width('100%').margin({ top: 20 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_DefaultFocus_title')) + } +} +// [End focus_visualization_manage] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusAndClick.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusAndClick.ets new file mode 100644 index 0000000000000000000000000000000000000000..f5aebe743e29b644ce9d13c1570b2d3e3a0c67d4 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusAndClick.ets @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { KeyCode } from '@kit.InputKit'; +import { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; + +// [Start dynamic_focus_click_count] +@Entry +@Component +export struct FocusAndClick { + @State count: number = 0; + @State name: string = 'Button'; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column() { + Button(this.name) + .fontSize(30) + .onClick(() => { + this.count++; + if (this.count <= 0) { + this.name = 'count is negative number'; + } else if (this.count % 2 === 0) { + this.name = 'count is even number'; + } else { + this.name = 'count is odd number'; + } + }).height(60) + }.height('100%').width('100%').justifyContent(FlexAlign.Center) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_FocusAndClick_title')) + } +} +// [End dynamic_focus_click_count] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusController.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusController.ets new file mode 100644 index 0000000000000000000000000000000000000000..9a282c3093f866dfe7ccbde177ac57bee2000714 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusController.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 { KeyCode } from '@kit.InputKit'; +import { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; + +// [Start dynamic_focus_control_demo] +@Entry +@Component +export struct FocusControl { + @State btColor: string = '#ff2787d9'; + @State btColor2: string = '#ff2787d9'; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 20 }) { + Column({ space: 5 }) { + Button('Button') + .width(200) + .height(70) + .fontColor(Color.White) + .focusOnTouch(true) + .backgroundColor(this.btColor) + .onFocus(() => { + this.btColor = '#ffd5d5d5'; + }) + .onBlur(() => { + this.btColor = '#ff2787d9'; + }) + .id('testButton') + + Button('Button') + .width(200) + .height(70) + .fontColor(Color.White) + .focusOnTouch(true) + .backgroundColor(this.btColor2) + .onFocus(() => { + this.btColor2 = '#ffd5d5d5'; + }) + .onBlur(() => { + this.btColor2 = '#ff2787d9'; + }) + .id('testButton2') + + Divider() + .vertical(false) + .width('80%') + .backgroundColor('#ff707070') + .height(10) + + Button('FocusController.requestFocus') + .width(200).height(70).fontColor(Color.White) + .onClick(() => { + this.getUIContext().getFocusController().requestFocus('testButton'); + }) + .backgroundColor('#ff2787d9') + + Button('focusControl.requestFocus') + .width(200).height(70).fontColor(Color.White) + .onClick(() => { + focusControl.requestFocus('testButton2'); + }) + .backgroundColor('#ff2787d9') + + Button('clearFocus') + .width(200).height(70).fontColor(Color.White) + .onClick(() => { + this.getUIContext().getFocusController().clearFocus(); + }) + .backgroundColor('#ff2787d9') + } + } + .width('100%') + .height('100%') + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_FocusController_title')) + } +} +// [End dynamic_focus_control_demo] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusPriority.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusPriority.ets new file mode 100644 index 0000000000000000000000000000000000000000..23e38577d10744c6646b7e14a48721f925a340b6 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusPriority.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 { KeyCode } from '@kit.InputKit'; + +// [Start focus_priority_manage] +@Entry +@Component +export struct FocusPrioritySample { + + build() { + NavDestination() { + Column({ space: 12 }) { + Column({ space: 8 }) { + Row() { + Button('Button1') + .defaultFocus(true) + Button('Button2') + .focusScopePriority('RowScope', FocusPriority.PREVIOUS) + }.focusScopeId('RowScope') + } + .alignItems(HorizontalAlign.Start) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_FocusPriority_title')) + } +} +// [End focus_priority_manage] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusScopePriority.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusScopePriority.ets new file mode 100644 index 0000000000000000000000000000000000000000..eae88de81d087426eb3206cbec9568109abaef5d --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusScopePriority.ets @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { KeyCode } from '@kit.InputKit'; +import { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; + +// [Start focus_scope_navigation] +@Entry +@Component +export struct FocusScopePriority { + @State inputValue: string = ''; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Scroll() { + Row({ space: 20 }) { + Column({ space: 20 }) { // 标记为Column1 + Column({ space: 5 }) { + Button('Group1') + .width(165) + .height(40) + .fontColor(Color.White) + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + } + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + } + }.borderWidth(2).borderColor(Color.Red).borderStyle(BorderStyle.Dashed) + Column({ space: 5 }) { + Button('Group2') + .width(165) + .height(40) + .fontColor(Color.White) + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + .focusScopePriority('ColumnScope1', FocusPriority.PRIOR) // Column1首次获焦时获焦 + } + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + } + }.borderWidth(2).borderColor(Color.Green).borderStyle(BorderStyle.Dashed) + } + .focusScopeId('ColumnScope1') + Column({ space: 5 }) { // 标记为Column2 + TextInput({placeholder: 'input', text: this.inputValue}) + .onChange((value: string) => { + this.inputValue = value; + }) + .width(156) + Button('Group3') + .width(165) + .height(40) + .fontColor(Color.White) + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + } + Button() + .width(165) + .height(40) + .fontColor(Color.White) + .focusScopePriority('ColumnScope2', FocusPriority.PREVIOUS) // Column2获焦时获焦 + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + } + Button() + .width(165) + .height(40) + .fontColor(Color.White) + Row({ space: 5 }) { + Button() + .width(80) + .height(40) + .fontColor(Color.White) + Button() + .width(80) + .height(40) + .fontColor(Color.White) + } + }.borderWidth(2).borderColor(Color.Orange).borderStyle(BorderStyle.Dashed) + .focusScopeId('ColumnScope2', true) // Column2为焦点组 + }.alignItems(VerticalAlign.Top) + } + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_FocusScopePriority_title')) + } +} +// [End focus_scope_navigation] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusStyle.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusStyle.ets new file mode 100644 index 0000000000000000000000000000000000000000..2841736de10f5d549f62ef9d926e3379de825a06 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/FocusStyle.ets @@ -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. + */ + +import { KeyCode } from '@kit.InputKit'; +import { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; + +// [Start focus_style_manage] +@Entry +@Component +export struct FocusStyle { + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 30 }) { + Button('small black focus box') + .focusBox({ + margin: new LengthMetrics(0), + strokeColor: ColorMetrics.rgba(0, 0, 0), + }) + Button('large red focus box') + .focusBox({ + margin: LengthMetrics.px(20), + strokeColor: ColorMetrics.rgba(255, 0, 0), + strokeWidth: LengthMetrics.px(10) + }) + } + .alignItems(HorizontalAlign.Center) + .width('100%') + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_FocusStyle_title')) + } +} +// [End focus_style_manage] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/Focusable.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/Focusable.ets new file mode 100644 index 0000000000000000000000000000000000000000..27a7def39df2e59a8edbc2b4e226db96179e677a --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/Focusable.ets @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { KeyCode } from '@kit.InputKit'; + +// [Start dynamic_focus_control_manage] +@Entry +@Component +export struct FocusableExample { + @State textFocusable: boolean = true; + @State textEnabled: boolean = true; + @State color1: Color = Color.Yellow; + @State color2: Color = Color.Yellow; + @State color3: Color = Color.Yellow; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Text($r('app.string.Focus_Focusable_text')) + .fontSize(14) + .fontColor('#666') + Column({ space: 5 }) { + Text('Default Text') // 第一个Text组件未设置focusable属性,默认不可获焦 + .borderColor(this.color1) + .borderWidth(2) + .width(300) + .height(70) + .onFocus(() => { + this.color1 = Color.Blue; + }) + .onBlur(() => { + this.color1 = Color.Yellow; + }) + Divider() + + Text('focusable: ' + this.textFocusable) // 第二个Text设置了focusable初始为true,focusableOnTouch为true + .borderColor(this.color2) + .borderWidth(2) + .width(300) + .height(70) + .focusable(this.textFocusable) + .focusOnTouch(true) + .onFocus(() => { + this.color2 = Color.Blue; + }) + .onBlur(() => { + this.color2 = Color.Yellow; + }) + + Text('enabled: ' + this.textEnabled) // 第三个Text设置了focusable为true,enabled初始为true + .borderColor(this.color3) + .borderWidth(2) + .width(300) + .height(70) + .focusable(true) + .enabled(this.textEnabled) + .focusOnTouch(true) + .onFocus(() => { + this.color3 = Color.Blue; + }) + .onBlur(() => { + this.color3 = Color.Yellow; + }) + + Divider() + + Row() { + Button('Button1') + .width(140).height(70) + Button('Button2') + .width(160).height(70) + } + + Divider() + Button('Button3') + .width(300).height(70) + + Divider() + }.width('100%').justifyContent(FlexAlign.Center) + .onKeyEvent((e) => { + // 绑定onKeyEvent,在该Column组件获焦时,按下'F'键,可将第二个Text的focusable置反 + if (e.keyCode === 2022 && e.type === KeyType.Down) { + this.textFocusable = !this.textFocusable; + } + // 绑定onKeyEvent,在该Column组件获焦时,按下'G'键,可将第三个Text的enabled置反 + if (e.keyCode === 2023 && e.type === KeyType.Down) { + this.textEnabled = !this.textEnabled; + } + }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_Focusable_title')) + } +} +// [End dynamic_focus_control_manage] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..af6f9d063e4b6a29b5e732d7008bb3d5d33cb4ff --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/Index.ets @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { DefaultFocus } from './DefaultFocus'; +import { FocusableExample } from './Focusable'; +import { FocusAndClick } from './FocusAndClick'; +import { FocusControl } from './FocusController'; +import { FocusPrioritySample } from './FocusPriority'; +import { FocusScopePriority } from './FocusScopePriority'; +import { FocusStyle } from './FocusStyle'; +import { OnFocusBlur } from './onFocusBlur'; +import resource from '../../common/resource'; + + +export const Focus_ROUTE_PREFIX: string = 'Focus_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${Focus_ROUTE_PREFIX}/onFocusBlur`, + title: resource.resourceToString($r('app.string.Focus_Index_onFocusBlur_title')), + description: resource.resourceToString($r('app.string.Focus_Index_onFocusBlur_description')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusableExample`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusableExample_title1')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusableExample_description1')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusableExample`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusableExample_title2')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusableExample_description2')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusableExample`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusableExample_title3')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusableExample_description3')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusStyle`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusStyle_title')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusStyle_description')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusControl`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusControl_title')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusControl_description')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusScopePriority`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusScopePriority_title')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusScopePriority_description')), + }, + { + name: `${Focus_ROUTE_PREFIX}/FocusAndClick`, + title: resource.resourceToString($r('app.string.Focus_Index_FocusAndClick_title')), + description: resource.resourceToString($r('app.string.Focus_Index_FocusAndClick_description')), + } +] + +@Builder +export function FocusDestination(name: string) { + if (name === Focus_ROUTE_PREFIX) { + FocusExample(); + } else if (name === routes[0].name) { + OnFocusBlur(); + } else if (name === routes[1].name) { + FocusableExample(); + } else if (name === routes[2].name) { + DefaultFocus(); + } else if (name === routes[3].name) { + FocusPrioritySample(); + } else if (name === routes[4].name) { + FocusStyle(); + } else if (name === routes[5].name) { + FocusControl(); + } else if (name === routes[6].name) { + FocusScopePriority(); + } else if (name === routes[7].name) { + FocusAndClick(); + } +} + +@Entry +@Component +struct FocusExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.Focus_Index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/focus/onFocusBlur.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/onFocusBlur.ets new file mode 100644 index 0000000000000000000000000000000000000000..4f993f6bef8dd5b4ac138a13fd380803d05b4748 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/focus/onFocusBlur.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 { KeyCode } from '@kit.InputKit'; + +// [Start focus_dynamic_reflect] +@Entry +@Component +export struct OnFocusBlur { + @State oneButtonColor: Color = Color.Gray; + @State twoButtonColor: Color = Color.Gray; + @State threeButtonColor: Color = Color.Gray; + + build() { + NavDestination() { + Column({ space: 12 }) { + + Column({ space: 20 }) { + // 通过外接键盘的上下键可以让焦点在三个按钮间移动,按钮获焦时颜色变化,失焦时变回原背景色 + Button('First Button') + .width(260) + .height(70) + .backgroundColor(this.oneButtonColor) + .fontColor(Color.Black) + // 监听第一个组件的获焦事件,获焦后改变颜色 + .onFocus(() => { + this.oneButtonColor = Color.Green; + }) + // 监听第一个组件的失焦事件,失焦后改变颜色 + .onBlur(() => { + this.oneButtonColor = Color.Gray; + }) + + Button('Second Button') + .width(260) + .height(70) + .backgroundColor(this.twoButtonColor) + .fontColor(Color.Black) + // 监听第二个组件的获焦事件,获焦后改变颜色 + .onFocus(() => { + this.twoButtonColor = Color.Green; + }) + // 监听第二个组件的失焦事件,失焦后改变颜色 + .onBlur(() => { + this.twoButtonColor = Color.Grey; + }) + + Button('Third Button') + .width(260) + .height(70) + .backgroundColor(this.threeButtonColor) + .fontColor(Color.Black) + // 监听第三个组件的获焦事件,获焦后改变颜色 + .onFocus(() => { + this.threeButtonColor = Color.Green; + }) + // 监听第三个组件的失焦事件,失焦后改变颜色 + .onBlur(() => { + this.threeButtonColor = Color.Gray; + }) + }.width('100%').margin({ top: 20 }) + + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.Focus_OnFocusBlur_title')) + } +} +// [End focus_dynamic_reflect] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/gesturejudge/GestureJudge.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/gesturejudge/GestureJudge.ets new file mode 100644 index 0000000000000000000000000000000000000000..bce286e8def63f96f3a88484190dc3e8038fe788 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/gesturejudge/GestureJudge.ets @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_judge] +// [Start set_gesture_judge] +@Entry +@Component +export struct GestureJudge { + scroller: Scroller = new Scroller(); + // [StartExclude set_gesture_judge] + 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; + // [EndExclude set_gesture_judge] + + build() { + NavDestination() { + Column({ space: 12 }) { + Text($r('app.string.gesture_GestureJudge_text')) + .fontSize(14) + .fontColor('#666') + 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.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; + }) + // [StartExclude set_gesture_judge] + .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; + }) + ) + // [EndExclude set_gesture_judge] + }.width('100%').height('90%').backgroundColor(0xDCDCDC) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.gesture_GestureJudge_title')) + } +} +// [End set_gesture_judge] +// [End gesture_judge] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/gesturejudge/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/gesturejudge/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b63a44b1a75893cb82dc619a03b8b71cfc597f0d --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/gesturejudge/Index.ets @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CompletedRoutableCard } from '../../common/Card'; +import { Route } from '../../common/Route'; +import { GestureJudge } from './GestureJudge'; +import resource from '../../common/resource'; + + +export const GestureJudge_ROUTE_PREFIX: string = 'GestureJudge_ROUTE_PREFIX'; + +const routes: Route[] = [ + { + name: `${GestureJudge_ROUTE_PREFIX}/GestureJudge`, + title: resource.resourceToString($r('app.string.gesture_Index_GestureJudge_title')), + description: resource.resourceToString($r('app.string.gesture_Index_GestureJudge_description')), + } +] + +@Builder +export function GestureJudgeDestination(name: string) { + if (name === GestureJudge_ROUTE_PREFIX) { + GestureJudgeExample(); + } else if (name === routes[0].name) { + GestureJudge(); + } +} + +@Entry +@Component +struct GestureJudgeExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.gesture_Index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Exclusive.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Exclusive.ets new file mode 100644 index 0000000000000000000000000000000000000000..a72dfbf7621f6bdfc0372a6a8093d27657d67be9 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Exclusive.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. + */ + +// [Start exclusive_recognition_gesture] +@Entry +@Component +export struct Exclusive { + @State count1: number = 0; + @State count2: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + Text($r('app.string.groupgesture_Exclusive_text')) + .fontSize(14) + .fontColor('#666') + Column() { + Text('Exclusive gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n') + .fontSize(28) + } + .height(200) + .width('100%') + //以下组合手势为互斥并别,单击手势识别成功后,双击手势会识别失败 + .gesture( + GestureGroup(GestureMode.Exclusive, + TapGesture({ count: 1 }) + .onAction(() => { + this.count1++; + }), + TapGesture({ count: 2 }) + .onAction(() => { + this.count2++; + }) + ) + ) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.groupgesture_Exclusive_title')) + } +} +// [End exclusive_recognition_gesture] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..f11dc4be9a09b79c040a623625751fb8339519a9 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/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 { Exclusive } from './Exclusive'; +import { Parallel } from './Parallel'; +import { Sequence } from './Sequence'; +import resource from '../../common/resource'; + +export const GroupGesture_ROUTE_PREFIX: string = 'GroupGestureExample'; + +const routes: Route[] = [ + { + name: `${GroupGesture_ROUTE_PREFIX}/Sequence`, + title: resource.resourceToString($r('app.string.groupgesture_Index_Sequence_title')), + description: resource.resourceToString($r('app.string.groupgesture_Index_Sequence_description')), + }, + { + name: `${GroupGesture_ROUTE_PREFIX}/Parallel`, + title: resource.resourceToString($r('app.string.groupgesture_Index_Parallel_title')), + description: resource.resourceToString($r('app.string.groupgesture_Index_Parallel_description')), + }, + { + name: `${GroupGesture_ROUTE_PREFIX}/Exclusive`, + title: resource.resourceToString($r('app.string.groupgesture_Index_Exclusive_title')), + description: resource.resourceToString($r('app.string.groupgesture_Index_Exclusive_description')), + } +] + +@Builder +export function GroupGestureDestination(name: string) { + if (name === GroupGesture_ROUTE_PREFIX) { + GroupGestureExample(); + } else if (name === routes[0].name) { + Sequence(); + } else if (name === routes[1].name) { + Parallel(); + } else if (name === routes[2].name) { + Exclusive(); + } +} + +@Entry +@Component +struct GroupGestureExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.groupgesture_Index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Parallel.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Parallel.ets new file mode 100644 index 0000000000000000000000000000000000000000..e08c5b8b0f39a0e7c3f1fd940f071033b311f7eb --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Parallel.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. + */ + +// [Start parallel_recognition_gesture] +@Entry +@Component +export struct Parallel { + @State count1: number = 0; + @State count2: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + Text($r('app.string.groupgesture_Parallel_text')) + .fontSize(14) + .fontColor('#666') + Column() { + Text('Parallel gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n') + .fontSize(28) + } + .height(200) + .width('100%') + // 以下组合手势为并行并别,单击手势识别成功后,若在规定时间内再次点击,双击手势也会识别成功 + .gesture( + GestureGroup(GestureMode.Parallel, + TapGesture({ count: 1 }) + .onAction(() => { + this.count1++; + }), + TapGesture({ count: 2 }) + .onAction(() => { + this.count2++; + }) + ) + ) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.groupgesture_Parallel_title')) + } +} +// [End parallel_recognition_gesture] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Sequence.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Sequence.ets new file mode 100644 index 0000000000000000000000000000000000000000..9f88c3236bfa63699cb0056f1c62165e458ae999 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/groupgesture/Sequence.ets @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 sequence_recognition_gesture] +@Entry +@Component +export struct Sequence { + @State offsetX: number = 0; + @State offsetY: number = 0; + @State count: number = 0; + @State positionX: number = 0; + @State positionY: number = 0; + @State borderStyles: BorderStyle = BorderStyle.Solid; + + build() { + NavDestination() { + Column({ space: 12 }) { + Text($r('app.string.groupgesture_Sequence_text')) + .fontSize(14) + .fontColor('#666') + Column() { + Text('sequence gesture\n' + 'LongPress onAction:' + this.count + '\nPanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY) + .fontSize(28) + }.margin(10) + .borderWidth(1) + // 绑定translate属性可以实现组件的位置移动 + .translate({ x: this.offsetX, y: this.offsetY, z: 0 }) + .height(250) + .width(300) + // 以下组合手势为顺序识别,当长按手势事件未正常触发时不会触发拖动手势事件 + .gesture( + // 声明该组合手势的类型为Sequence类型 + GestureGroup(GestureMode.Sequence, + // 该组合手势第一个触发的手势为长按手势,且长按手势可多次响应 + LongPressGesture({ repeat: true }) + // 当长按手势识别成功,增加Text组件上显示的count次数 + .onAction((event: GestureEvent|undefined) => { + if(event){ + if (event.repeat) { + this.count++; + } + } + console.info('LongPress onAction'); + }) + .onActionEnd(() => { + console.info('LongPress end'); + }), + // 当长按之后进行拖动,PanGesture手势被触发 + PanGesture() + .onActionStart(() => { + this.borderStyles = BorderStyle.Dashed; + console.info('pan start'); + }) + // 当该手势被触发时,根据回调获得拖动的距离,修改该组件的位移距离从而实现组件的移动 + .onActionUpdate((event: GestureEvent|undefined) => { + if(event){ + this.offsetX = (this.positionX + event.offsetX); + this.offsetY = this.positionY + event.offsetY; + } + console.info('pan update'); + }) + .onActionEnd(() => { + this.positionX = this.offsetX; + this.positionY = this.offsetY; + this.borderStyles = BorderStyle.Solid; + }) + ) + .onCancel(() => { + console.log('sequence gesture canceled'); + }) + ) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.groupgesture_Sequence_title')) + } +} +// [End sequence_recognition_gesture] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/Index.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..44b5aa020cdab03e6fac9e0803ec8fc232b33f30 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/Index.ets @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { LongPress } from './LongPressGesture'; +import { Pan } from './PanGesture'; +import { Pinch } from './PinchGesture'; +import { Rotation } from './RotationGesture'; +import { Swipe } from './SwipeGesture'; +import { Tap } from './TapGesture'; +import resource from '../../common/resource'; + +export const Gesture_ROUTE_PREFIX: string = 'gesture'; + +const routes: Route[] = [ + { + name: `${Gesture_ROUTE_PREFIX}/TapGesture`, + title: resource.resourceToString($r('app.string.singlegesture_Index_TapGesture_title')), + description: resource.resourceToString($r('app.string.singlegesture_Index_TapGesture_description')), + }, + { + name: `${Gesture_ROUTE_PREFIX}/LongPress`, + title: resource.resourceToString($r('app.string.singlegesture_Index_LongPress_title')), + description: resource.resourceToString($r('app.string.singlegesture_Index_LongPress_description')), + }, + { + name: `${Gesture_ROUTE_PREFIX}/Pan`, + title: resource.resourceToString($r('app.string.singlegesture_Index_Pan_title')), + description: resource.resourceToString($r('app.string.singlegesture_Index_Pan_description')), + }, + { + name: `${Gesture_ROUTE_PREFIX}/Pinch`, + title: resource.resourceToString($r('app.string.singlegesture_Index_Pinch_title')), + description: resource.resourceToString($r('app.string.singlegesture_Index_Pinch_description')), + }, + { + name: `${Gesture_ROUTE_PREFIX}/Rotation`, + title: resource.resourceToString($r('app.string.singlegesture_Index_Rotation_title')), + description: resource.resourceToString($r('app.string.singlegesture_Index_Rotation_description')), + }, + { + name: `${Gesture_ROUTE_PREFIX}/Swipe`, + title: resource.resourceToString($r('app.string.singlegesture_Index_Swipe_title')), + description: resource.resourceToString($r('app.string.singlegesture_Index_Swipe_description')), + } +] + +@Builder +export function GestureDestination(name: string) { + if (name === Gesture_ROUTE_PREFIX) { + GestureExample(); + } else if (name === routes[0].name) { + Tap(); + } else if (name === routes[1].name) { + LongPress(); + } else if (name === routes[2].name) { + Pan(); + } else if (name === routes[3].name) { + Pinch(); + } else if (name === routes[4].name) { + Rotation(); + } else if (name === routes[5].name) { + Swipe(); + } +} + +@Entry +@Component +struct GestureExample { + @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(20) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + .title($r('app.string.singlegesture_Index_title')) + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/LongPressGesture.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/LongPressGesture.ets new file mode 100644 index 0000000000000000000000000000000000000000..ddf02d55f8e294dec314a645bcc821231df11515 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/LongPressGesture.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. + */ + +// [Start catch_long_press_event] +@Entry +@Component +export struct LongPress { + @State count: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Text('LongPress OnAction:' + this.count).fontSize(28) + .gesture( + // 绑定可以重复触发的LongPressGesture + LongPressGesture({ repeat: true }) + .onAction((event: GestureEvent | undefined) => { + if (event) { + if (event.repeat) { + this.count++; + } + } + }) + .onActionEnd(() => { + this.count = 0; + }) + ) + } + .height(200) + .width(250) + .padding(20) + .border({ width: 3 }) + .margin(30) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.singlegesture_LongPressGesture_title')) + } +} +// [End catch_long_press_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/PanGesture.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/PanGesture.ets new file mode 100644 index 0000000000000000000000000000000000000000..7afb75ff6ca1b5cf15717cd7e7de66d46703d35c --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/PanGesture.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. + */ + +// [Start catch_pan_gesture_event] +@Entry +@Component +export struct Pan { + @State offsetX: number = 0; + @State offsetY: number = 0; + @State positionX: number = 0; + @State positionY: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Text('PanGesture Offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY) + .fontSize(28) + .height(200) + .width(300) + .padding(20) + .border({ width: 3 }) + // 在组件上绑定布局位置信息 + .translate({ x: this.offsetX, y: this.offsetY, z: 0 }) + .gesture( + // 绑定拖动手势 + PanGesture() + .onActionStart((event: GestureEvent|undefined) => { + console.info('Pan start'); + }) + // 当触发拖动手势时,根据回调函数修改组件的布局位置信息 + .onActionUpdate((event: GestureEvent|undefined) => { + if(event){ + this.offsetX = this.positionX + event.offsetX; + this.offsetY = this.positionY + event.offsetY; + } + }) + .onActionEnd(() => { + this.positionX = this.offsetX; + this.positionY = this.offsetY; + }) + ) + } + .height(200) + .width(250) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.singlegesture_PanGesture_title')) + } +} +// [End catch_pan_gesture_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/PinchGesture.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/PinchGesture.ets new file mode 100644 index 0000000000000000000000000000000000000000..9d538513c66b652bdc2f018ab2a6e39680133f94 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/PinchGesture.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. + */ + +// [Start catch_pinch_gesture_event] +@Entry +@Component +export struct Pinch { + @State scaleValue: number = 1; + @State pinchValue: number = 1; + @State pinchX: number = 0; + @State pinchY: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Column() { + Text('PinchGesture scale:\n' + this.scaleValue) + Text('PinchGesture center:\n(' + this.pinchX + ',' + this.pinchY + ')') + } + .height(200) + .width(300) + .border({ width: 3 }) + .margin({ top: 100 }) + // 在组件上绑定缩放比例,可以通过修改缩放比例来实现组件的缩小或者放大 + .scale({ x: this.scaleValue, y: this.scaleValue, z: 1 }) + .gesture( + // 在组件上绑定三指触发的捏合手势 + PinchGesture({ fingers: 3 }) + .onActionStart((event: GestureEvent | undefined) => { + console.info('Pinch start'); + })// 当捏合手势触发时,可以通过回调函数获取缩放比例,从而修改组件的缩放比例 + .onActionUpdate((event: GestureEvent | undefined) => { + if (event) { + this.scaleValue = this.pinchValue * event.scale; + this.pinchX = event.pinchCenterX; + this.pinchY = event.pinchCenterY; + } + }) + .onActionEnd(() => { + this.pinchValue = this.scaleValue; + console.info('Pinch end'); + }) + ) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.singlegesture_PinchGesture_title')) + } +} +// [End catch_pinch_gesture_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/RotationGesture.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/RotationGesture.ets new file mode 100644 index 0000000000000000000000000000000000000000..89d5775e8815a222812b4917c7c2244d310c5f7f --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/RotationGesture.ets @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start catch_rotation_gesture_event] +@Entry +@Component +export struct Rotation { + @State angle: number = 0; + @State rotateValue: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Text('RotationGesture angle:' + this.angle).fontSize(28) + // 在组件上绑定旋转布局,可以通过修改旋转角度来实现组件的旋转 + .rotate({ angle: this.angle }) + .gesture( + RotationGesture() + .onActionStart((event: GestureEvent|undefined) => { + console.info('RotationGesture is onActionStart'); + }) + // 当旋转手势生效时,通过旋转手势的回调函数获取旋转角度,从而修改组件的旋转角度 + .onActionUpdate((event: GestureEvent|undefined) => { + if(event){ + this.angle = this.rotateValue + event.angle; + } + console.info('RotationGesture is onActionEnd'); + }) + // 当旋转结束抬手时,固定组件在旋转结束时的角度 + .onActionEnd(() => { + this.rotateValue = this.angle; + console.info('RotationGesture is onActionEnd'); + }) + .onActionCancel(() => { + console.info('RotationGesture is onActionCancel'); + }) + ) + .height(200) + .width(300) + .padding(20) + .border({ width: 3 }) + .margin(100) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.singlegesture_RotationGesture_title')) + } +} +// [End catch_rotation_gesture_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/SwipeGesture.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/SwipeGesture.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b4363855344f460e3efba6f37bba0e5c8b15bdb --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/SwipeGesture.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start catch_swipe_gesture_event] +@Entry +@Component +export struct Swipe { + @State rotateAngle: number = 0; + @State speed: number = 1; + + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Column() { + Text('SwipeGesture speed\n' + this.speed) + Text('SwipeGesture angle\n' + this.rotateAngle) + } + .border({ width: 3 }) + .width(300) + .height(200) + .margin(100) + // 在Column组件上绑定旋转,通过滑动手势的滑动速度和角度修改旋转的角度 + .rotate({ angle: this.rotateAngle }) + .gesture( + // 绑定滑动手势且限制仅在竖直方向滑动时触发 + SwipeGesture({ direction: SwipeDirection.Vertical }) + // 当滑动手势触发时,获取滑动的速度和角度,实现对组件的布局参数的修改 + .onAction((event: GestureEvent|undefined) => { + if(event){ + this.speed = event.speed; + this.rotateAngle = event.angle; + } + }) + ) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.singlegesture_SwipeGesture_title')) + } +} +// [End catch_swipe_gesture_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/TapGesture.ets b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/TapGesture.ets new file mode 100644 index 0000000000000000000000000000000000000000..bc0f24b52c56514c5b2140e60fb35d3dde4f6769 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/ets/pages/singlegesture/TapGesture.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 catch_click_twice_event] +@Entry +@Component +export struct Tap { + @State value: string = ''; + + build() { + NavDestination() { + Column({ space: 12 }) { + Column() { + Text('Click twice').fontSize(28) + .gesture( + // 绑定count为2的TapGesture + TapGesture({ count: 2 }) + .onAction((event: GestureEvent|undefined) => { + if(event){ + this.value = JSON.stringify(event.fingerList[0]); + } + })) + Text(this.value) + } + .height(200) + .width(250) + .padding(20) + .border({ width: 3 }) + .margin(30) + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.singlegesture_TapGesture_title')) + } +} +// [End catch_click_twice_event] \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/module.json5 b/ArkUISample/EventProject/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4144486d1af4c03b0d767cce1cda86fc0d697f91 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/module.json5 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/resources/base/element/color.json b/ArkUISample/EventProject/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/main/resources/base/element/string.json b/ArkUISample/EventProject/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..145f10cab5f469295f7bce1511ed617798bdb980 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/resources/base/element/string.json @@ -0,0 +1,420 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "EventProject" + }, + { + "name": "HoverEffectSample_title", + "value": "悬浮状态" + }, + { + "name": "Hover_Event", + "value": "悬浮事件" + }, + { + "name": "Hover_Description", + "value": "鼠标悬浮事件回调。参数isHover类型为boolean,表示鼠标进入组件或离开组件。该事件不支持自定义冒泡设置,默认父子冒泡" + }, + { + "name": "Mouse_Event", + "value": "鼠标事件" + }, + { + "name": "Mouse_Description", + "value": "鼠标事件回调。绑定该API的组件每当鼠标指针在该组件内产生行为(MouseAction)时,触发事件回调,参数为MouseEvent对象,表示触发此次的鼠标事件。该事件支持自定义冒泡设置,默认父子冒泡。常用于开发者自定义的鼠标行为逻辑处理。" + }, + { + "name": "Hover_Effect", + "value": "鼠标悬浮态效果" + }, + { + "name": "Hover_Effect_Description", + "value": "鼠标悬浮态效果设置的通用属性。参数类型为HoverEffect,HoverEffect提供的Auto、Scale、Highlight效果均为固定效果,开发者无法自定义设置效果参数。" + }, + { + "name": "Key_Event", + "value": "按键事件" + }, + { + "name": "Key_Description", + "value": "按键事件由外设键盘等设备触发,经驱动和多模处理转换后发送给当前获焦的窗口,窗口获取到事件后,会尝试分发三次事件。" + }, + { + "name": "Key_PreIme", + "value": "屏蔽" + }, + { + "name": "Key_PreIme_Description", + "value": "使用OnKeyPreIme屏蔽在输入框中使用方向左键。" + }, + { + "name": "Device_index_title", + "value": "键鼠事件" + }, + { + "name": "Device_OnHover_title", + "value": "悬浮事件" + }, + { + "name": "Device_OnKey_title", + "value": "按键事件" + }, + { + "name": "Device_OnKeyPreIme_title", + "value": "按键事件" + }, + { + "name": "Device_OnMouse_title", + "value": "鼠标事件" + }, + { + "name": "Drag_DefaultDrag_title", + "value": "通用拖拽" + }, + { + "name": "Drag_Index_DefaultDrag_title", + "value": "通用拖拽" + }, + { + "name": "Drag_Index_DefaultDrag_description", + "value": "组件使能拖拽。设置draggable属性为true,并配置onDragStart回调函数。" + }, + { + "name": "Drag_Index_MoreDrag_title", + "value": "多选拖拽" + }, + { + "name": "Drag_Index_MoreDrag_description", + "value": "从API version 12开始,Grid组件和List组件中的GridItem和ListItem组件支持多选与拖拽功能。目前,仅支持onDragStart的触发方式。" + }, + { + "name": "Drag_Index_title", + "value": "拖拽事件" + }, + { + "name": "Drag_MoreDrag_title", + "value": "多选拖拽" + }, + { + "name": "Focus_DefaultFocus_title", + "value": "默认焦点" + }, + { + "name": "Focus_Focusable_title", + "value": "设置组件是否可获焦" + }, + { + "name": "Focus_Focusable_text", + "value": "当某组件处于获焦状态时,将其的focusable属性或enabled属性设置为false,会自动使该组件失焦,然后焦点按照走焦规范将焦点转移给其他组件。" + }, + { + "name": "Focus_FocusAndClick_title", + "value": "焦点与按键事件" + }, + { + "name": "Focus_FocusController_title", + "value": "主动获焦/失焦" + }, + { + "name": "Focus_FocusPriority_title", + "value": "容器默认焦点" + }, + { + "name": "Focus_FocusScopePriority_title", + "value": "焦点组与获焦优先级" + }, + { + "name": "Focus_FocusStyle_title", + "value": "焦点样式" + }, + { + "name": "Focus_Index_title", + "value": "焦点事件" + }, + { + "name": "Focus_Index_onFocusBlur_title", + "value": "获焦失焦" + }, + { + "name": "Focus_Index_FocusableExample_title1", + "value": "设置是否可获焦" + }, + { + "name": "Focus_Index_FocusableExample_title2", + "value": "页面的默认焦点" + }, + { + "name": "Focus_Index_FocusableExample_title3", + "value": "容器的默认焦点" + }, + { + "name": "Focus_Index_FocusStyle_title", + "value": "焦点样式" + }, + { + "name": "Focus_Index_FocusControl_title", + "value": "主动获焦/失焦" + }, + { + "name": "Focus_Index_FocusScopePriority_title", + "value": "焦点组与获焦优先级" + }, + { + "name": "Focus_Index_FocusAndClick_title", + "value": "焦点与按键事件" + }, + { + "name": "Focus_Index_onFocusBlur_description", + "value": "获焦事件回调,绑定该接口的组件获焦时,回调响应。失焦事件回调,绑定该接口的组件失焦时,回调响应。" + }, + { + "name": "Focus_Index_FocusableExample_description1", + "value": "设置组件是否可获焦。" + }, + { + "name": "Focus_Index_FocusableExample_description2", + "value": "设置当前组件是否为当前页面上的默认焦点。" + }, + { + "name": "Focus_Index_FocusableExample_description3", + "value": "FocusPriority是用于指定某个容器首次获焦时其子节点的获焦优先级。" + }, + { + "name": "Focus_Index_FocusStyle_description", + "value": "设置当前组件系统焦点框样式。" + }, + { + "name": "Focus_Index_FocusControl_description", + "value": "使用FocusController中的方法。更推荐使用FocusController中的requestFocus主动获取焦点。" + }, + { + "name": "Focus_Index_FocusScopePriority_description", + "value": "focusScopePriority(scopeId: string, priority?: FocusPriority)设置当前组件在指定容器内获焦的优先级。需要配合focusScopeId一起使用。" + }, + { + "name": "Focus_Index_FocusAndClick_description", + "value": "当组件获焦且存在点击事件(onClick)或单指单击事件(TapGesture)时,回车和空格会触发对应的事件回调。" + }, + { + "name": "Focus_OnFocusBlur_title", + "value": "获焦/失焦事件" + }, + { + "name": "gesture_GestureJudge_text", + "value": "以下示例中,Image和Stack两个组件位于同一区域。长按Stack组件的上半部分可触发挂载在Stack组件上的长按手势,长按Stack组件的下半部分则会响应Image组件的拖拽操作。" + }, + { + "name": "gesture_GestureJudge_title", + "value": "手势拦截" + }, + { + "name": "gesture_Index_title", + "value": "手势拦截" + }, + { + "name": "gesture_Index_GestureJudge_title", + "value": "手势拦截" + }, + { + "name": "gesture_Index_GestureJudge_description", + "value": "手势拦截主要用于确保手势按需执行,有效解决手势冲突问题。典型应用场景包括:嵌套滚动、通过过滤组件响应手势的范围来优化交互体验。手势拦截主要采用手势触发控制和手势响应控制两种方式实现。" + }, + { + "name": "groupgesture_Exclusive_text", + "value": "以在一个Column组件上绑定单击手势和双击手势组合而成的互斥识别组合手势为例。若先绑定单击手势后绑定双击手势,由于单击手势只需要一次点击即可触发而双击手势需要两次,每次的点击事件均被单击手势消费而不能积累成双击手势,所以双击手势无法触发。若先绑定双击手势后绑定单击手势,则触发双击手势不触发单击手势。" + }, + { + "name": "groupgesture_Exclusive_title", + "value": "互斥识别" + }, + { + "name": "groupgesture_Parallel_text", + "value": "以在一个Column组件上绑定点击手势和双击手势组成的并行识别手势为例,由于单击手势和双击手势是并行识别,因此两个手势可以同时进行识别,二者互不干涉。" + }, + { + "name": "groupgesture_Parallel_title", + "value": "并行识别" + }, + { + "name": "groupgesture_Sequence_text", + "value": "'在一个Column组件上绑定了translate属性,通过修改该属性可以设置组件的位置移动。然后在该组件上绑定LongPressGesture和PanGesture组合而成的Sequence组合手势。当触发LongPressGesture时,更新显示的数字。当长按后进行拖动时,根据拖动手势的回调函数,实现组件的拖动。" + }, + { + "name": "groupgesture_Sequence_title", + "value": "顺序识别" + }, + { + "name": "groupgesture_Index_title", + "value": "组合手势" + }, + { + "name": "groupgesture_Index_Sequence_title", + "value": "顺序识别" + }, + { + "name": "groupgesture_Index_Parallel_title", + "value": "并行识别" + }, + { + "name": "groupgesture_Index_Exclusive_title", + "value": "互斥识别" + }, + { + "name": "groupgesture_Index_Sequence_description", + "value": "顺序识别组合手势对应的GestureMode为Sequence。顺序识别组合手势将按照手势的注册顺序识别手势,直到所有的手势识别成功。当顺序识别组合手势中有一个手势识别失败时,后续手势识别均失败。顺序识别手势组仅有最后一个手势可以响应onActionEnd。" + }, + { + "name": "groupgesture_Index_Parallel_description", + "value": "并行识别组合手势对应的GestureMode为Parallel。并行识别组合手势中注册的手势将同时进行识别,直到所有手势识别结束。并行识别手势组合中的手势进行识别时互不影响。" + }, + { + "name": "groupgesture_Index_Exclusive_description", + "value": "互斥识别组合手势对应的GestureMode为Exclusive。互斥识别组合手势中注册的手势将同时进行识别,若有一个手势识别成功,则结束手势识别,其他所有手势识别失败。" + }, + { + "name": "singlegesture_LongPressGesture_title", + "value": "长按手势" + }, + { + "name": "singlegesture_PanGesture_title", + "value": "拖动手势" + }, + { + "name": "singlegesture_PinchGesture_title", + "value": "捏合手势" + }, + { + "name": "singlegesture_RotationGesture_title", + "value": "旋转手势" + }, + { + "name": "singlegesture_SwipeGesture_title", + "value": "滑动手势" + }, + { + "name": "singlegesture_TapGesture_title", + "value": "点击手势" + }, + { + "name": "singlegesture_Index_title", + "value": "单一手势" + }, + { + "name": "singlegesture_Index_TapGesture_title", + "value": "点击手势" + }, + { + "name": "singlegesture_Index_LongPress_title", + "value": "长按手势" + }, + { + "name": "singlegesture_Index_Pan_title", + "value": "拖动手势" + }, + { + "name": "singlegesture_Index_Pinch_title", + "value": "捏合手势" + }, + { + "name": "singlegesture_Index_Rotation_title", + "value": "旋转手势" + }, + { + "name": "singlegesture_Index_Swipe_title", + "value": "滑动手势" + }, + { + "name": "singlegesture_Index_TapGesture_description", + "value": "单一手势的使用示例,点击手势支持单次点击和多次点击,拥有两个可选参数。" + }, + { + "name": "singlegesture_Index_LongPress_description", + "value": "长按手势用于触发长按手势事件。" + }, + { + "name": "singlegesture_Index_Pan_description", + "value": "拖动手势用于触发拖动手势事件,滑动达到最小滑动距离(默认值为5vp)时拖动手势识别成功。" + }, + { + "name": "singlegesture_Index_Pinch_description", + "value": "捏合手势用于触发捏合手势事件。其中示例为三指捏合" + }, + { + "name": "singlegesture_Index_Rotation_description", + "value": "旋转手势用于触发旋转手势事件,拥有两个可选参数:fingers:用于声明触发旋转手势所需要的最少手指数量,最小值为2,最大值为5,默认值为2。angle:用于声明触发旋转手势的最小改变度数,单位为deg,默认值为1" + }, + { + "name": "singlegesture_Index_Swipe_description", + "value": "滑动手势用于触发滑动事件,当滑动速度大于100vp/s时可以识别成功,拥有三个可选参数:fingers:用于声明触发滑动手势所需要的最少手指数量,最小值为1,最大值为10,默认值为1。direction:用于声明触发滑动手势的方向,此枚举值支持逻辑与(&)和逻辑或(|)运算。默认值为SwipeDirection.All。speed:用于声明触发滑动的最小滑动识别速度,单位为vp/s,默认值为100。" + }, + { + "name": "Touch_ClickEvent_text", + "value": "通过按钮的点击事件控制图片的显示和隐藏。" + }, + { + "name": "Touch_ClickEvent_title", + "value": "点击事件" + }, + { + "name": "Touch_TouchEvent_title", + "value": "触摸事件" + }, + { + "name": "Touch_Index_title", + "value": "触摸事件" + }, + { + "name": "Touch_Index_ClickEvent_title", + "value": "点击事件" + }, + { + "name": "Touch_Index_TouchEvent_title", + "value":"触摸事件" + }, + { + "name": "Touch_Index_ClickEvent_description", + "value": "点击事件是指通过手指或手写笔做出一次完整的按下和抬起动作。当发生点击事件时,会触发以下回调函数:\n onClick(event: (event?: ClickEvent) => void)\n 'event参数提供点击事件相对于窗口或组件的坐标位置,以及发生点击的事件源。" + }, + { + "name": "Touch_Index_TouchEvent_description", + "value": "当手指或手写笔在组件上触碰时,会触发不同动作所对应的事件响应,包括按下(Down)、滑动(Move)、抬起(Up)事件。" + }, + { + "name": "Pages_Index_gesture", + "value": "单一手势/gesture" + }, + { + "name": "Pages_Index_GroupGesture", + "value": "组合手势/GroupGesture" + }, + { + "name": "Pages_Index_GestureJudge", + "value": "手势拦截/GestureJudge" + }, + { + "name": "Pages_Index_TouchEvent", + "value": "触摸事件/TouchEvent" + }, + { + "name": "Pages_Index_DeviceEvent", + "value": "键鼠事件/DeviceEvent" + }, + { + "name": "Pages_Index_FocusEvent", + "value": "焦点事件/FocusEvent" + }, + { + "name": "Pages_Index_DragEvent", + "value": "拖拽事件/DragEvent" + } + ] +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/resources/base/media/background.png b/ArkUISample/EventProject/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ArkUISample/EventProject/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUISample/EventProject/entry/src/main/resources/base/media/foreground.png b/ArkUISample/EventProject/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ArkUISample/EventProject/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUISample/EventProject/entry/src/main/resources/base/media/layered_image.json b/ArkUISample/EventProject/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/main/resources/base/media/startIcon.png b/ArkUISample/EventProject/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUISample/EventProject/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUISample/EventProject/entry/src/main/resources/base/profile/backup_config.json b/ArkUISample/EventProject/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/main/resources/base/profile/main_pages.json b/ArkUISample/EventProject/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ArkUISample/EventProject/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ArkUISample/EventProject/entry/src/main/resources/dark/element/color.json b/ArkUISample/EventProject/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/mock/mock-config.json5 b/ArkUISample/EventProject/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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/ArkUISample/EventProject/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUISample/EventProject/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/ohosTest/ets/test/Index.test.ets b/ArkUISample/EventProject/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..6bfc92ee7a0c2b90c95e9a5891c4e5ccf4cfa350 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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'; +// 导入测试依赖kit +import { abilityDelegatorRegistry, Driver, ON, MouseButton, Component, MatchPattern } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import resource from '../../../main/ets/common/resource'; + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let want: Want; + +export default function IndexTest() { + + describe('IndexTest', () => { + + beforeAll(async () => { + want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver = Driver.create(); + await driver.delayMs(1000); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info('get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + }) + + /** + * @tc.number UiTest_001 + * @tc.name testSingleGestureTap + * @tc.desc 测试点击手势示例 + */ + it('testSingleGestureTap', 0, async (done: Function) => { + console.info('uitest: testSingleGestureTap begin'); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text('gesture', MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.singlegesture_Index_TapGesture_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + //已进入测试界面 + let button2 = await driver.findComponent(ON.text('twice', MatchPattern.CONTAINS)); + await button2.doubleClick(); + await driver.delayMs(1000); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSingleGestureTap end'); + done(); + }) + + /** + * @tc.number UiTest_002 + * @tc.name testSingleGestureLong + * @tc.desc 测试长按手势示例 + */ + it('testSingleGestureLong', 0, async (done: Function) => { + console.info('uitest: testSingleGestureLong begin'); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text('gesture', MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.singlegesture_Index_LongPress_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + //已进入测试界面 + let button2 = await driver.findComponent(ON.text('Long', MatchPattern.CONTAINS)); + await button2.longClick(); + await driver.delayMs(1000); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSingleGestureLong end'); + done(); + }) + + /** + * @tc.number UiTest_003 + * @tc.name testSingleGestureJudge + * @tc.desc 测试手势拦截示例 + */ + it('testSingleGestureJudge', 0, async (done: Function) => { + console.info('uitest: testSingleGestureJudge begin'); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text('GestureJudge', MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.gesture_Index_GestureJudge_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + //已进入测试界面 + await driver.delayMs(1000); + await driver.pressBack(); + console.info('uitest: testSingleGestureJudge end'); + done(); + }) + + /** + * @tc.number UiTest_004 + * @tc.name testSingleGestureTouch + * @tc.desc 测试点击事件示例 + */ + it('testSingleGestureTouch', 0, async (done: Function) => { + console.info('uitest: testSingleGestureTouch begin'); + let driver = Driver.create(); + let button_list = await driver.findComponent(ON.text('TouchEvent', MatchPattern.CONTAINS)); + expect(button_list === null).assertFalse(); + await button_list.click(); + let button_list1 = await driver.findComponent(ON.text(resource.resourceToString($r('app.string.Touch_Index_ClickEvent_title')), MatchPattern.CONTAINS)); + await button_list1.click(); + //已进入测试界面 + let button = await driver.findComponent(ON.text('show', MatchPattern.CONTAINS)); + await button.click(); + await driver.delayMs(1000); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSingleGestureTouch end'); + done(); + }) + + + }) +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/ohosTest/ets/test/List.test.ets b/ArkUISample/EventProject/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..ea9e8f2599127c8910ef4de9260913e346cc32d4 --- /dev/null +++ b/ArkUISample/EventProject/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 IndexTest from './Index.test'; +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); + IndexTest(); +} \ No newline at end of file diff --git a/ArkUISample/EventProject/entry/src/ohosTest/module.json5 b/ArkUISample/EventProject/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ArkUISample/EventProject/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ArkUISample/EventProject/entry/src/test/List.test.ets b/ArkUISample/EventProject/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/entry/src/test/LocalUnit.test.ets b/ArkUISample/EventProject/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/hvigor/hvigor-config.json5 b/ArkUISample/EventProject/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/hvigorfile.ts b/ArkUISample/EventProject/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/ArkUISample/EventProject/hvigorfile.ts @@ -0,0 +1,6 @@ +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/ArkUISample/EventProject/oh-package.json5 b/ArkUISample/EventProject/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/ArkUISample/EventProject/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/ArkUISample/EventProject/screenshots/device/image1.png b/ArkUISample/EventProject/screenshots/device/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..3175478e318bd7c2a75fd63c27be1a515600fd61 Binary files /dev/null and b/ArkUISample/EventProject/screenshots/device/image1.png differ diff --git a/ArkUISample/EventProject/screenshots/device/image2.png b/ArkUISample/EventProject/screenshots/device/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..cc7ea0f6e37b32d8fb78df3fa92119901d09cffb Binary files /dev/null and b/ArkUISample/EventProject/screenshots/device/image2.png differ diff --git a/ArkUISample/EventProject/screenshots/device/image3.png b/ArkUISample/EventProject/screenshots/device/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..42f997e0bfebd0e150de46bcf0cf38f65ad6f0cd Binary files /dev/null and b/ArkUISample/EventProject/screenshots/device/image3.png differ