diff --git a/ArkUIKit/ScrollableComponent/.gitignore b/ArkUIKit/ScrollableComponent/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/.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/ArkUIKit/ScrollableComponent/AppScope/app.json5 b/ArkUIKit/ScrollableComponent/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..92ed3a36e833607bc64578b181c20330a75dafe2 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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.scrollablecomponent", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ArkUIKit/ScrollableComponent/AppScope/resources/base/element/string.json b/ArkUIKit/ScrollableComponent/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..0f965de3af08def5019fc97d5107ecd98928fd97 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ScrollableComponent" + } + ] +} diff --git a/ArkUIKit/ScrollableComponent/AppScope/resources/base/media/app_icon.png b/ArkUIKit/ScrollableComponent/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/AppScope/resources/base/media/app_icon.png differ diff --git a/ArkUIKit/ScrollableComponent/README_zh.md b/ArkUIKit/ScrollableComponent/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..5b7104c0f73d6d420c9e319f290a47ec33725a75 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/README_zh.md @@ -0,0 +1,151 @@ +# ArkUI使用滚动类指南文档示例 + +### 介绍 + +本示例通过使用[ArkUI指南文档](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-development)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: + +1. [创建列表 (List)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-list)。 +2. [创建弧形列表 (ArcList)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-arclist)(圆形屏幕推荐使用) +3. [创建网格 (Grid/GridItem)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-grid)。 +4. [创建瀑布流 (WaterFlow)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-waterflow) +5. [创建轮播 (Swiper)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-looping)。 +6. [创建弧形轮播 (ArcSwiper)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-arcswiper)(圆形屏幕推荐使用) +7. [选项卡 (Tabs)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-tabs) +### 效果预览 + +| 首页 | 列表类组件目录 | 列表中显示数据示例 | +|------------------------------------|------------------------------------|------------------------------------| +| ![](screenshots/device/image1.png) | ![](screenshots/device/image2.png) | ![](screenshots/device/image3.png) | + +### 使用说明 + +1. 在主界面,可以点击对应卡片,选择需要参考的组件示例。 + +2. 在组件目录选择详细的示例参考。 + +3. 进入示例界面,查看参考示例。 + +4. 通过自动测试框架可进行测试及维护。 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +|---pages +| |---arcList //弧形列表 +| | |---ArcListAcrScrollBar.ets +| | |---ArcListArcIndexerBar.ets +| | |---arcListBuiltInScrollerBar.ets +| | |---ArcListContents.ets +| | |---ArcListCrown.ets +| | |---ArcListShow.ets +| | |---ArcListSideSlip.ets +| | |---ArcListStyles.ets +| | |---ArcLongList.ets +| | |---index.ets +| |---arcSwiper //弧形轮播 +| | |---ArcSwiperAction.ets +| | |---ArcSwiperHorizontal.ets +| | |---ArcSwiperSideSlip.ets +| | |---ArcSwiperStyles.ets +| | |---ArcSwiperToggle.ets +| | |---ArcSwiperVertical.ets +| | |---index.ets +| |---grid //网格 +| | |---DataInGrid.ets +| | |---GridCalculator.ets +| | |---GridDataSource.ets +| | |---GridLayout.ets +| | |---GridScrollbar.ets +| | |---GridSideToSide.ets +| | |---index.ets +| | |---LongGrid.ets +| | |---ScrollableGrid.ets +| | |---ScrollPosition.ets +| |---list //列表 +| | |---AddListItem.ets +| | |---CollapseAndExpand.ets +| | |---ControlledScrollPositionList.ets +| | |---CustomListStyle.ets +| | |---DataInList.ets +| | |---DeleteListItem.ets +| | |---GroupedList.ets +| | |---index.ets +| | |---ListChatRoom.ets +| | |---ListDataSource.ets +| | |---ListIteration.ets +| | |---ListLayout.ets +| | |---LongList.ets +| | |---ResponsiveScrollPositionList.ets +| | |---StickyHeaderList.ets +| | |---SwipeListItem.ets +| | |---TaggedListItems.ets +| |---swiper //轮播 +| | |---index.ets +| | |---SwiperAndTabsLinkage.ets +| | |---SwiperAutoPlay.ets +| | |---SwiperCustomAnimation.ets +| | |---SwiperDirection.ets +| | |---SwiperIgnoreComponentSize.ets +| | |---SwiperIndicatorStyle.ets +| | |---SwiperLoop.ets +| | |---SwiperMultiPage.ets +| | |---SwiperPageSwitchMethod.ets +| |---tabs //选项卡 +| | |---AgeFriendlyTabs.ets +| | |---BottomTabBar.ets +| | |---ContentWillChange.ets +| | |---CustomTabBar.ets +| | |---FixedTabBar.ets +| | |---index.ets +| | |---ScrollableTabBar.ets +| | |---SideTabBar.ets +| | |---SwipeLockedTabBar.ets +| | |---TabsLayout.ets +| | |---TopTabBar.ets +| |---waterFlow //瀑布流 +| | |---AgeFriendlyTabs.ets +| | |---BottomTabBar.ets +| | |---ContentWillChange.ets +| | |---CustomTabBar.ets +| | |---FixedTabBar.ets +| | |---index.ets +| | |---WaterFlowDataSource.ets +| | |---WaterFlowDynamicSwitchover.ets +| | |---WaterFlowGroupingMixing.ets +| | |---WaterFlowInfiniteScrolling.ets +| | |---WaterFlowInfiniteScrollingEarly.ets +|---pages +| |---Index.ets // 应用主页面 +entry/src/ohosTest/ +|---ets +| |---index.test.ets // 示例代码测试代码 +``` + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行, 支持设备:RK3568。 + +2.本示例为Stage模型,支持API18版本full-SDK,版本号:5.1.0.107,镜像版本号:OpenHarmony_5.1.0 Release。 + +3.本示例需要使用DevEco Studio 5.0.5 Release (Build Version: 5.0.13.200, built on May 13, 2025)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo code/DocsSample/ArkUIDocSample/ScrollableComponent > .git/info/sparse-checkout +git remote add origin https://gitee.com/openharmony/applications_app_samples.git +git pull origin master +```` \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/build-profile.json5 b/ArkUIKit/ScrollableComponent/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b17b9042c1982deb930f28d08cd5984488b13274 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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", + "compileSdkVersion": 18, + "compatibleSdkVersion": 18, + "targetSdkVersion": 18, + "runtimeOS": "OpenHarmony", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/code-linter.json5 b/ArkUIKit/ScrollableComponent/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/.gitignore b/ArkUIKit/ScrollableComponent/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/build-profile.json5 b/ArkUIKit/ScrollableComponent/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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/ArkUIKit/ScrollableComponent/entry/hvigorfile.ts b/ArkUIKit/ScrollableComponent/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e4f43d54667f8327c367c8096bd08bb8c75aff54 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ArkUIKit/ScrollableComponent/entry/obfuscation-rules.txt b/ArkUIKit/ScrollableComponent/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/oh-package.json5 b/ArkUIKit/ScrollableComponent/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/Card.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/Card.ets new file mode 100644 index 0000000000000000000000000000000000000000..8eef9a0fc9b2138668c3048c8076d9db3e453c85 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/Card.ets @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Component +export struct CompletedRoutableCard { + @Prop + symbol: Resource = $r('sys.symbol.label'); + @Prop + @Require + title: string; + @Prop + @Require + description: ResourceStr; + + build() { + Card({ verticalAlign: VerticalAlign.Top }) { + Button({ type: ButtonType.Circle }) { + SymbolGlyph(this.symbol) + .fontColor(['#fff']) + .fontSize(16) + } + .borderRadius(14) + + Column({ space: 8 }) { + Text(this.title) + .fontColor($r('sys.color.font_primary')) + + Text(this.description) + .fontColor($r('sys.color.font_secondary')) + .fontSize($r('sys.float.Body_S')) + } + .alignItems(HorizontalAlign.Start) + .layoutWeight(1) + } + } +} + +@Component +export struct Card { + @Prop + verticalAlign: VerticalAlign = VerticalAlign.Center; + @BuilderParam + content: () => void; + + build() { + Row({ space: 12 }) { + this.content() + } + .alignItems(this.verticalAlign) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + } +} + +@Component +export struct RoutableCard { + @Prop + icon: Resource = $r('sys.symbol.label'); + @Prop + @Require + title: ResourceStr; + + build() { + Card() { + Button({ type: ButtonType.Circle }) { + SymbolGlyph(this.icon) + .fontColor(['#fff']) + .fontSize(16) + } + .borderRadius(14) + + Text(this.title) + .fontColor($r('sys.color.font_primary')) + .minFontSize(12) + .maxFontSize(16) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + + Blank() + + Button({ type: ButtonType.Normal, buttonStyle: ButtonStyleMode.TEXTUAL }) { + SymbolGlyph($r('sys.symbol.chevron_right')) + .fontSize(18) + .fontColor([$r('sys.color.font_secondary')]) + } + } + } +} + +@Component +export struct ComponentCard { + @Prop + @Require + title: ResourceStr; + @BuilderParam content: () => void; + @Prop + description?: ResourceStr; + + build() { + Column({ space: 8 }) { + Text(this.title) + .fontSize(14) + .fontColor('#666') + Row({ space: 12}) { + this.content(); + } + if (this.description) { + Text(this.description) + .backgroundColor('#eee') + .borderRadius(4) + .padding(4) + .fontSize(12) + .fontColor('#999') + .width('100%') + } + } + .alignItems(HorizontalAlign.Start) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/Route.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/Route.ets new file mode 100644 index 0000000000000000000000000000000000000000..da3d2cc3284d5cba7d3b667a3c1c61f5c6b5a9dc --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/Route.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Route { + title: string ; + name: string; + items?: Route[]; + description?: ResourceStr; +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/resource.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/resource.ets new file mode 100644 index 0000000000000000000000000000000000000000..e240a1079ad09a0f19080b49b57a6a0720416e6c --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/common/resource.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class ResourceManager { + public resourceToString(resource: Resource): string { + return getContext(this).resourceManager.getStringSync(resource); + } +} + +// 默认导出let +let resourceToStringManager = new ResourceManager(); + +export default resourceToStringManager as ResourceManager; \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/entryability/EntryAbility.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..edc2839f203ba057c186e19b0cbbbf80c8faa8b3 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/Index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..be9cdd168523a39eec9f2753548c165d168b2da0 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { gridDestination, GRID_ROUTE_PREFIX } from './grid'; +import { List_ROUTE_PREFIX, listDestination } from './list/Index'; +import { LengthMetrics } from '@kit.ArkUI'; +import { Route } from '../common/Route'; +import { RoutableCard } from '../common/Card'; +import { swiperDestination, SWIPER_ROUTE_PREFIX } from './swiper'; +import { waterFlowDestination, WATERFLOW_ROUTE_PREFIX } from './waterFlow'; +import { tabsDestination, TABS_ROUTE_PREFIX } from './tabs'; +import { arcSwiperDestination, ARCSWIPER_ROUTE_PREFIX } from './arcSwiper'; +import { arcListDestination, ARCLIST_ROUTE_PREFIX } from './arcList'; +import resource from '../common/resource'; + +const routes: Route[] = [ + { + title: resource.resourceToString($r('app.string.pageIndex_List')), + name: List_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_ArcList')), + name: ARCLIST_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_Grid')), + name: GRID_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_WaterFlow')), + name: WATERFLOW_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_Swiper')), + name: SWIPER_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_ArcSwiper')), + name: ARCSWIPER_ROUTE_PREFIX + }, + { + title: resource.resourceToString($r('app.string.pageIndex_Tabs')), + name: TABS_ROUTE_PREFIX + } +]; + +@Builder +function destination(name: string) { + if (name.startsWith(List_ROUTE_PREFIX)) { + listDestination(name); + } else if (name.startsWith(GRID_ROUTE_PREFIX)) { + gridDestination(name); + } else if (name.startsWith(SWIPER_ROUTE_PREFIX)) { + swiperDestination(name); + } else if (name.startsWith(ARCSWIPER_ROUTE_PREFIX)) { + arcSwiperDestination(name); + } else if (name.startsWith(TABS_ROUTE_PREFIX)) { + tabsDestination(name); + } else if (name.startsWith(WATERFLOW_ROUTE_PREFIX)) { + waterFlowDestination(name); + } else if (name.startsWith(ARCLIST_ROUTE_PREFIX)) { + arcListDestination(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/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListAcrScrollBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListAcrScrollBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..6cb9df1e993b96d6c2dd6864df78c656fad4c23d --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListAcrScrollBar.ets @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { + ArcList, + ArcListItem, + ArcListAttribute, + ArcListItemAttribute, + LengthMetrics, + ArcScrollBar, +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcListAcrScrollBar { + private arcListScroller: Scroller = new Scroller(); + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcListAcrScrollBar_title') }) { + ArcList({ scroller: this.arcListScroller }) { + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_waln')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.blueTooth')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_blue')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_net')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.ic_settings_more_connections')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_connect')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_light')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + } + .width('466px') + .height('466px') + .space(LengthMetrics.px(10)) + .borderRadius('233px') + .backgroundColor(Color.Black) + + ArcScrollBar({ scroller: this.arcListScroller }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListAcrScrollBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListArcIndexerBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListArcIndexerBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..ca16ea3554d04747c3e6b5d323ab0bb5f56d9442 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListArcIndexerBar.ets @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ArcList, ArcListAttribute, ArcListItemAttribute, ArcListItem, LengthMetrics } from '@kit.ArkUI'; +import { ColorMetrics, ComponentContent } from '@ohos.arkui.node'; +import { util } from '@kit.ArkTS'; +import { ArcAlphabetIndexer, ArcAlphabetIndexerAttribute } from '@ohos.arkui.ArcAlphabetIndexer'; +import { ComponentCard } from '../../common/Card'; + +class Contact { + key: string = util.generateRandomUUID(true); + name: string; + firstChar: string; + + constructor(name: string, firstChar: string) { + this.name = name; + this.firstChar = firstChar; + } +} +@Builder +function buildText() { + Column() { + Text('Contacts') + .fontColor('#FFFFFF') + .fontSize('19fp') + + } +} + +@Entry +@Component +export struct ArcListArcIndexerBar { + + @State contacts: Array = [ + new Contact('阿哈', 'A'), + new Contact('贝贝', 'B'), + new Contact('彩彩', 'C'), + new Contact('东东', 'D'), + new Contact('嗯嗯', 'E'), + new Contact('芳芳', 'F'), + new Contact('哥哥', 'G'), + new Contact('哈哈', 'H'), + new Contact('吉吉', 'J'), + new Contact('可可', 'K'), + new Contact('乐乐', 'L'), + new Contact('妹妹', 'M'), + new Contact('妮妮', 'N'), + new Contact('哦豁', 'O'), + new Contact('胖胖', 'P'), + new Contact('琪琪', 'Q'), + new Contact('然然', 'R'), + new Contact('叔叔', 'S'), + new Contact('天天', 'T'), + ]; + private scrollerForList: Scroller = new Scroller(); + private watchSize: string = '600px'; // 手表默认宽高:233*233 + private fullValue: string[] = [ + '#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' + ]; + @State indexerIndex: number = 0; + + context: UIContext = this.getUIContext(); + tabBar1: ComponentContent = new ComponentContent(this.context, wrapBuilder(buildText)); + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcListArcIndexerBar_title') }) { + Stack() { + ArcList({ initialIndex: 0, header:this.tabBar1, scroller:this.scrollerForList }) { + ForEach(this.contacts, (item: Contact) => { + ArcListItem() { + Row() { + Text(item.firstChar) + .textAlign(TextAlign.Center) + .width(30) + .height(30) + .margin(10) + .backgroundColor('#FF9CC998') + .borderRadius(20) + Text(item.name).fontSize('38px').fontColor('#FFFFFFFF') + } + .width('100%') + .justifyContent(FlexAlign.Start) + } + .borderRadius('65px') + .width('370px') + .height('130px') + .backgroundColor('#26FFFFFF') + }, (item: Contact) => JSON.stringify(item)) + } + .space(LengthMetrics.px(10)) + .scrollBar(BarState.Off) + .width(this.watchSize) + .height(this.watchSize) + .borderRadius(this.watchSize) + .backgroundColor(Color.Black) + .onScrollIndex((firstIndex: number, lastIndex: number, centerIndex: number) => { + this.indexerIndex = centerIndex + 1; + }) + + ArcAlphabetIndexer({ arrayValue: this.fullValue, selected: this.indexerIndex}) + .autoCollapse(true) + .width(this.watchSize) + .height(this.watchSize) + .usePopup(false) + .selected(this.indexerIndex!!) + .onSelect((index: number) => { + this.indexerIndex = index + this.scrollerForList.scrollToIndex(this.indexerIndex - 1) + }) + .hitTestBehavior(HitTestMode.Transparent) + .selectedColor(ColorMetrics.resourceColor(0xFFFFFF)) + .selectedBackgroundColor(ColorMetrics.resourceColor(0x1F71FF)) + .color(ColorMetrics.resourceColor(0xFFFFFF)) + .popupColor(ColorMetrics.resourceColor(0xFFFFFF)) + .popupBackground(ColorMetrics.resourceColor(0xD8404040)) + .itemSize(LengthMetrics.px(12)) + .selectedFont({ + size: '11.0fp', + style: FontStyle.Normal, + weight: 500, + family: 'HarmonyOS Sans' + }) + .font({ + size: '11.0fp', + style: FontStyle.Normal, + weight: 500, + family: 'HarmonyOS Sans' + }) + + }.width('600px') + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListArcIndexerBar_title')) + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListContents.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListContents.ets new file mode 100644 index 0000000000000000000000000000000000000000..007f3911dd50fe7ca9eaa42f51c2be455f09b0ad --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListContents.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. + */ + +import { ArcList, ArcListAttribute, ArcListItemAttribute, ArcListItem, LengthMetrics } from '@kit.ArkUI'; +import { util } from '@kit.ArkTS'; +import { ComponentCard } from '../../common/Card'; + +class Contact { + key: string = util.generateRandomUUID(true); + name: string; + icon: Resource; + + constructor(name: string, icon: Resource) { + this.name = name; + this.icon = icon; + } +} + +@Entry +@Component +export struct ArcListContents { + private contacts: Array = [ + new Contact('小红', $r('app.media.ic_contact')), + new Contact('小兰', $r('app.media.ic_contact')), + new Contact('小王', $r('app.media.ic_contact')), + new Contact('小李', $r('app.media.ic_contact')), + new Contact('小明', $r('app.media.ic_contact')) + ]; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcListContents_title') }) { + ArcList({ initialIndex: 2 }) { + ForEach(this.contacts, (item: Contact) => { + ArcListItem() { + Row() { + Image(item.icon) + .width(40) + .height(40) + .margin(10) + .backgroundColor('#FF9CC998') + .borderRadius(20) + Text(item.name).fontSize('38px').fontColor('#FFFFFFFF') + } + .width('100%') + .justifyContent(FlexAlign.Start) + } + .borderRadius('65px') + .width('410px') + .height('130px') + .backgroundColor('#26FFFFFF') + }, (item: Contact) => JSON.stringify(item)) + } + .space(LengthMetrics.px(10)) + .width('466px') + .height('466px') + .borderRadius('233px') + .backgroundColor(Color.Black) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListContents_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListCrown.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListCrown.ets new file mode 100644 index 0000000000000000000000000000000000000000..cc76cdd3cb9dcb943ca881973e60b9eb965a8712 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListCrown.ets @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; +import { ArcList, ArcListItem, ArcListAttribute, ArcListItemAttribute } from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Builder +function buildText() { + Column() { + Text($r('app.string.ArcListCrown_set')) + .fontColor('#FFFFFF') + .fontSize('19fp') + + }.height(10) +} + +@Entry +@Component +export struct ArcListCrown { + private watchSize: string = '466px'; // 手表默认宽高:466*466 + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcListCrown_title') }) { + Stack() { + ArcList({ + initialIndex: 2, + }) { + ArcListItem() { + Text('Network').fontSize('38px').fontColor('#FFFFFFFF') + } + .borderRadius('65px') + .width('414px') + .height('50px') + .autoScale(false) + + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('80px').height('80px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text('WLAN').fontSize('38px').fontColor('#FFFFFFFF') + Text('On').fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('80px').height('80px') + .borderRadius('50px') + } + + } + .borderRadius('65px') + .width('414px') + .height('100px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('80px').height('80px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text('Bluetooth').fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('80px').height('80px') + .borderRadius('50px') + } + + } + .borderRadius('65px') + .width('414px') + .height('100px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Text('Display').fontSize('38px').fontColor('#FFFFFFFF') + } + .borderRadius('65px') + .width('414px') + .height('50px') + .autoScale(false) + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('80px').height('80px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text('Display & brightness').fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('80px').height('80px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('100px') + .backgroundColor('#26FFFFFF') + } + .space(LengthMetrics.px(10)) + .scrollBarWidth(LengthMetrics.px(10)) + .scrollBarColor(ColorMetrics.resourceColor(Color.White)) + .borderRadius(this.watchSize) + .focusable(true) + .focusOnTouch(true) + .defaultFocus(true) + } + .align(Alignment.Center) + .width(this.watchSize) + .height(this.watchSize) + .borderRadius(this.watchSize) + .backgroundColor(Color.Black) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListCrown_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListShow.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListShow.ets new file mode 100644 index 0000000000000000000000000000000000000000..932600a062460483ac317ddba7abce9249dbe6bc --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListShow.ets @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ArcList, ArcListItem, ArcListAttribute, ArcListItemAttribute, LengthMetrics, } from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcListShow { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcListShow_title') }) { + ArcList({ initialIndex: 2 }) { + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_waln')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.blueTooth')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_blue')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_net')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.ic_settings_more_connections')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_connect')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_light')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + } + .width('466px') + .height('466px') + .space(LengthMetrics.px(10)) + .borderRadius('233px') + .backgroundColor(Color.Black) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListShow_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListSideSlip.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListSideSlip.ets new file mode 100644 index 0000000000000000000000000000000000000000..ce364a1d3495111550eda7d0bca4206abf81f1f9 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListSideSlip.ets @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ArcList, ArcListAttribute, ArcListItemAttribute, ArcListItem } from '@kit.ArkUI'; +import { ComponentContent, LengthMetrics } from '@ohos.arkui.node'; +import { util } from '@kit.ArkTS'; +import { ComponentCard } from '../../common/Card'; + +class Contact { + key: string = util.generateRandomUUID(true); + name: string; + firstChar: string; + + constructor(name: string, firstChar: string) { + this.name = name; + this.firstChar = firstChar; + } +} +@Builder +function buildText() { + Column() { + Text('Contacts ') + .fontColor('#FFFFFF') + .fontSize('19fp') + + } +} + +@Entry +@Component +export struct ArcListSideSlip { + @State contacts: Array = [ + new Contact('Alice', 'A'), + new Contact('Bob', 'B'), + new Contact('Charlie', 'C'), + new Contact('Diana', 'D'), + new Contact('Eve', 'E'), + new Contact('阿哈', 'A'), + new Contact('贝贝', 'B'), + new Contact('彩彩', 'C'), + new Contact('东东', 'D'), + new Contact('嗯嗯', 'E'), + new Contact('芳芳', 'F'), + new Contact('哥哥', 'G'), + new Contact('哈哈', 'H'), + new Contact('吉吉', 'J'), + new Contact('可可', 'K'), + new Contact('乐乐', 'L'), + new Contact('妹妹', 'M'), + new Contact('妮妮', 'N'), + new Contact('哦豁', 'O'), + new Contact('胖胖', 'P'), + new Contact('琪琪', 'Q'), + new Contact('然然', 'R'), + new Contact('叔叔', 'S'), + new Contact('天天', 'T'), + ]; + + private scrollerForList: Scroller = new Scroller(); + + @State indexerIndex: number = 0; + context: UIContext = this.getUIContext(); + tabBar1: ComponentContent = new ComponentContent(this.context, wrapBuilder(buildText)); + + @Builder + itemEnd(item: Contact) { + // 构建尾端滑出组件 + Button({ type: ButtonType.Circle }) { + Image($r('app.media.MaterialSymbolsDelete')) + .width(20) + .height(20) + } + .width(20) + .height(20) + .backgroundColor(Color.Black) + .onClick(() => { + this.getUIContext()?.animateTo({ + duration: 1000, + curve: Curve.Smooth, + iterations: 1, + playMode: PlayMode.Normal, + }, () => { + let index = this.contacts.indexOf(item); + this.contacts.splice(index, 1); + }) + + }) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcListSideSlip_title') }) { + Stack() { + ArcList({ initialIndex: 0, header: this.tabBar1, scroller: this.scrollerForList }) { + ForEach(this.contacts, (item: Contact) => { + ArcListItem() { + Row() { + Text(item.firstChar) + .textAlign(TextAlign.Center) + .width(30) + .height(30) + .margin(10) + .backgroundColor('#FF9CC998') + .borderRadius(20) + Text(item.name).fontSize('38px').fontColor('#FFFFFFFF') + } + .backgroundColor('#26FFFFFF') + .borderRadius('65px') + .width('90%') + .justifyContent(FlexAlign.Start) + } + .swipeAction({ + end: { + // index为该ArcListItem在ArcList中的索引值。 + builder: () => { + this.itemEnd(item); + }, + } + }) // 设置侧滑属性. + .borderRadius('65px') + .width('400px') + .height('130px') + + }, (item: Contact) => JSON.stringify(item)) + } + .space(LengthMetrics.px(10)) + .scrollBar(BarState.Auto) + .width('466px') + .height('466px') + .borderRadius('233px') + .backgroundColor(Color.Black) + .margin(50) + .onScrollIndex((firstIndex: number, lastIndex: number, centerIndex: number) => { + this.indexerIndex = centerIndex + 1; + }) + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListSideSlip_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListStyles.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListStyles.ets new file mode 100644 index 0000000000000000000000000000000000000000..d3452e6ba7f8f05c5df4a15dee0d94cab2ff54b7 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListStyles.ets @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { + ArcList, + ArcListItem, + ArcListAttribute, + ArcListItemAttribute, + LengthMetrics, + ComponentContent +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Builder +function customHeader() { + Column() { + Text($r('app.string.ArcListCrown_set')) + .fontColor('#FFFFFFFF') + .fontSize('19fp') + } +} + + +@Entry +@Component +export struct ArcListStyles { + context: UIContext = this.getUIContext(); + arcListHeader: ComponentContent = new ComponentContent(this.context, wrapBuilder(customHeader)); + + build() { + NavDestination() { + Column({ space: 12 }) { + List(){ + ListItem(){ + ComponentCard({ title: $r('app.string.ArcListStyles_head') }) { + ArcList({ header: this.arcListHeader }) { + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_waln')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.blueTooth')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_blue')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_net')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.ic_settings_more_connections')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_connect')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_light')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + } + .width('466px') + .height('466px') + .space(LengthMetrics.px(10)) + .borderRadius('233px') + .backgroundColor(Color.Black) + } + } + + ListItem(){ + ComponentCard({ title: $r('app.string.ArcListStyles_titleSpacing') }) { + ArcList({ initialIndex: 2 }) { + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_waln')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.blueTooth')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_blue')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_net')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.ic_settings_more_connections')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_connect')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_light')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + } + .width('466px') + .height('466px') + .space(LengthMetrics.px(30)) + .borderRadius('233px') + .backgroundColor(Color.Black) + + } + } + + ListItem(){ + ComponentCard({ title: $r('app.string.ArcListStyles_titleScale') }) { + ArcList({ initialIndex: 2 }) { + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_waln')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.blueTooth')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_blue')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_net')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + .autoScale(false) + + ArcListItem() { + Row() { + Image($r('app.media.ic_settings_more_connections')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_connect')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_light')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + .autoScale(false) + } + .width('466px') + .height('466px') + .space(LengthMetrics.px(30)) + .borderRadius('233px') + .backgroundColor(Color.Black) + } + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcListStyles_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcLongList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcLongList.ets new file mode 100644 index 0000000000000000000000000000000000000000..6ddd21ef91d42add85eb674413d50693f0df0a36 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcLongList.ets @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ArcList, ArcListAttribute, ArcListItemAttribute, ArcListItem } from '@kit.ArkUI'; +import { LengthMetrics } from '@ohos.arkui.node'; +import { ComponentCard } from '../../common/Card'; + +class BasicDataSource implements IDataSource { + private listeners: DataChangeListener[] = []; + private originDataArray: StringData[] = []; + + public totalCount(): number { + return 0; + } + + public getData(index: number): StringData { + return this.originDataArray[index]; + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener'); + this.listeners.push(listener); + } + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener'); + this.listeners.splice(pos, 1); + } + } + + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }); + } + + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }); + } + + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }); + } + + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }); + } + + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }); + } + + notifyDatasetChange(operations: DataOperation[]): void { + this.listeners.forEach(listener => { + listener.onDatasetChange(operations); + }); + } +} + +class MyDataSource extends BasicDataSource { + private dataArray: StringData[] = []; + + public totalCount(): number { + return this.dataArray.length; + } + + public getData(index: number): StringData { + return this.dataArray[index]; + } + + public pushData(data: StringData): void { + this.dataArray.push(data); + this.notifyDataAdd(this.dataArray.length - 1); + } +} + +@Observed +class StringData { + message: string; + + constructor(message: string) { + this.message = message; + } +} + +@Entry +@Component +export struct ArcLongList { + private data: MyDataSource = new MyDataSource(); + + aboutToAppear() { + for (let i = 0; i <= 100; i++) { + this.data.pushData(new StringData(`Hello ${i}`)); + } + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcLongList_title') }) { + ArcList() { + LazyForEach(this.data, (item: StringData, index: number) => { + ArcListItem() { + Text(item.message).fontSize(30).fontColor(Color.White) + } + .onClick(() => { + item.message += '0'; + }) + }, (item: StringData, index: number) => JSON.stringify(item) + index.toString()) + }.cachedCount(3) + .space(LengthMetrics.px(10)) + .scrollBar(BarState.Auto) + .width('466px') + .height('466px') + .borderRadius('233px') + .backgroundColor(Color.Black) + .margin(50) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcLongList_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/arcListBuiltInScrollerBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/arcListBuiltInScrollerBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..f38604db4abcad1d3eb7fe6d91386fcb1c9d411f --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/arcListBuiltInScrollerBar.ets @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ArcList, ArcListItem, ArcListAttribute, ArcListItemAttribute, LengthMetrics, ColorMetrics } from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct arcListBuiltInScrollerBar { + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.arcListBuiltInScrollerBar_title') }) { + ArcList() { + ArcListItem() { + Row() { + Image($r('app.media.wlan')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_waln')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.blueTooth')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_blue')).fontSize('38px').fontColor('#FFFFFFFF') + Text($r('app.string.ArcListStyles_open')).fontSize('20px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.mobileData')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_net')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.ic_settings_more_connections')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_connect')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + + ArcListItem() { + Row() { + Image($r('app.media.displayAndBrightness')).width('99px').height('99px') + .borderRadius('50px').margin({ left: 7 }) + Column() { + Text($r('app.string.ArcListStyles_light')).fontSize('38px').fontColor('#FFFFFFFF') + }.width('190px') + + Image($r('app.media.ic_settings_arrow')).width('92px').height('92px') + .borderRadius('50px') + } + } + .borderRadius('65px') + .width('414px') + .height('129px') + .backgroundColor('#26FFFFFF') + } + .width('466px') + .height('466px') + .space(LengthMetrics.px(10)) + .borderRadius('233px') + .backgroundColor(Color.Black) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.arcListBuiltInScrollerBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b2b874b86cf2ef6da31a8d4aa1a8d3ac845e95fd --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcList/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 { CompletedRoutableCard } from '../../common/Card'; +import { Route } from '../../common/Route'; +import { ArcListAcrScrollBar } from './ArcListAcrScrollBar'; +import { ArcListArcIndexerBar } from './ArcListArcIndexerBar'; +import { arcListBuiltInScrollerBar } from './arcListBuiltInScrollerBar'; +import { ArcListContents } from './ArcListContents'; +import { ArcListCrown } from './ArcListCrown'; +import { ArcListShow } from './ArcListShow'; +import { ArcListSideSlip } from './ArcListSideSlip'; +import { ArcListStyles } from './ArcListStyles'; +import { ArcLongList } from './ArcLongList'; + +import resource from '../../common/resource'; + +export const ARCLIST_ROUTE_PREFIX: string = 'arcList'; + +const routes: Route[] = [ + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListShow`, + title: resource.resourceToString($r('app.string.ArcListShow_title')), + description: $r('app.string.ArcListShow_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListContents`, + title: resource.resourceToString($r('app.string.ArcListContents_title')), + description: $r('app.string.ArcListContents_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListStyles`, + title: resource.resourceToString($r('app.string.ArcListStyles_title')), + description: $r('app.string.ArcListStyles_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/arcListBuiltInScrollerBar`, + title: resource.resourceToString($r('app.string.arcListBuiltInScrollerBar_title')), + description: $r('app.string.arcListBuiltInScrollerBar_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListAcrScrollBar`, + title: resource.resourceToString($r('app.string.ArcListAcrScrollBar_title')), + description: $r('app.string.ArcListAcrScrollBar_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListArcIndexerBar`, + title: resource.resourceToString($r('app.string.ArcListArcIndexerBar_title')), + description: $r('app.string.ArcListArcIndexerBar_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListSideSlip`, + title: resource.resourceToString($r('app.string.ArcListSideSlip_title')), + description: $r('app.string.ArcListSideSlip_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcLongList`, + title: resource.resourceToString($r('app.string.ArcLongList_title')), + description: $r('app.string.ArcLongList_description') + }, + { + name: `${ARCLIST_ROUTE_PREFIX}/ArcListCrown`, + title: resource.resourceToString($r('app.string.ArcListCrown_title')), + description: $r('app.string.ArcListCrown_description') + } +]; + +@Builder +export function arcListDestination(name: string) { + if (name === ARCLIST_ROUTE_PREFIX) { + ArcListExample(); + } else if (name === routes[0].name) { + ArcListShow(); + } else if (name === routes[1].name) { + ArcListContents(); + } else if (name === routes[2].name) { + ArcListStyles(); + } else if (name === routes[3].name) { + arcListBuiltInScrollerBar(); + } else if (name === routes[4].name) { + ArcListAcrScrollBar(); + } else if (name === routes[5].name) { + ArcListArcIndexerBar(); + } else if (name === routes[6].name) { + ArcListSideSlip(); + } else if (name === routes[7].name) { + ArcLongList(); + } else if (name === routes[8].name) { + ArcListCrown(); + } +} + +@Entry +@Component +struct ArcListExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('ArcList', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperAction.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperAction.ets new file mode 100644 index 0000000000000000000000000000000000000000..d7f1f0af987e314896998fd453ee0d0905692d02 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperAction.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. + */ + +import { Decimal } from '@kit.ArkTS'; +import { + ArcSwiper, + ArcSwiperAttribute, +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcSwiperAction { + private MIN_SCALE: number = 0.1; + @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange]; + @State opacityList: number[] = []; + @State scaleList: number[] = []; + + aboutToAppear(): void { + for (let i = 0; i < this.backgroundColors.length; i++) { + this.opacityList.push(1.0); + this.scaleList.push(1.0); + } + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcSwiperAction_title') }) { + ArcSwiper() { + ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => { + Text(index.toString()) + .width(233) + .height(233) + .fontSize(50) + .textAlign(TextAlign.Center) + .backgroundColor(backgroundColor) + .opacity(this.opacityList[index]) + .scale({ x: this.scaleList[index], y: this.scaleList[index] }) + }) + } + .customContentTransition({ + timeout: 1000, + transition: (proxy: SwiperContentTransitionProxy) => { + if (proxy.position <= -1 || proxy.position >= 1) { + // 页面完全滑出视窗外时,重置属性值 + this.opacityList[proxy.index] = 1.0; + this.scaleList[proxy.index] = 1.0; + } else { + let position: number = Decimal.abs(proxy.position).toNumber(); + this.opacityList[proxy.index] = 1 - position; + this.scaleList[proxy.index] = + this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - position); + } + } + }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcSwiperAction_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperHorizontal.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperHorizontal.ets new file mode 100644 index 0000000000000000000000000000000000000000..47d538edcbc3bac7bba2cea7f8e10c588061d6b0 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperHorizontal.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 { + ArcSwiper, + ArcSwiperAttribute, +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcSwiperHorizontal { + @State message: string = 'Hello World'; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcSwiperHorizontal_title') }) { + ArcSwiper() { + Text('0') + .width(233) + .height(233) + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width(233) + .height(233) + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width(233) + .height(233) + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + .indicator(true) + .vertical(false) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcSwiperHorizontal_title')) + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperSideSlip.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperSideSlip.ets new file mode 100644 index 0000000000000000000000000000000000000000..af64879aee82cd2758e3bab79a60b911c54b904e --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperSideSlip.ets @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ArcSwiper, + ArcSwiperAttribute, + ArcDotIndicator, + ArcDirection, + ArcSwiperController +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcSwiperSideSlip { + @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange]; + innerSelectedIndex: number = 0; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcSwiperSideSlip_title') }) { + ArcSwiper() { + ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => { + Text(index.toString()) + .width(233) + .height(233) + .fontSize(50) + .textAlign(TextAlign.Center) + .backgroundColor(backgroundColor) + }) + } + .onAnimationStart((index: number, targetIndex: number) => { + this.innerSelectedIndex = targetIndex; + }) + .onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer, + others: Array): GestureJudgeResult => { // 在识别器即将要成功时,根据当前组件状态,设置识别器使能状态 + if (current) { + let target = current.getEventTargetInfo(); + if (target && current.isBuiltIn() && current.getType() == GestureControl.GestureType.PAN_GESTURE) { + let swiperTarget = target as ScrollableTargetInfo; + if (swiperTarget instanceof ScrollableTargetInfo && + (swiperTarget.isBegin() || this.innerSelectedIndex === 0)) { // 此处判断swiperTarget.isBegin()或innerSelectedIndex === 0,表明ArcSwiper滑动到开头 + let panEvent = event as PanGestureEvent; + if (panEvent && panEvent.offsetX > 0 && (swiperTarget.isBegin() || this.innerSelectedIndex === 0)) { + return GestureJudgeResult.REJECT; + } + } + } + } + return GestureJudgeResult.CONTINUE; + }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcSwiperSideSlip_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperStyles.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperStyles.ets new file mode 100644 index 0000000000000000000000000000000000000000..11bf5dd57c629e5e812e2d555e3e8d07c1f51a1a --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperStyles.ets @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { + ArcSwiper, + ArcSwiperAttribute, + ArcDotIndicator, + ArcDirection, + ArcSwiperController +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcSwiperStyles { + @State message: string = 'Hello World'; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcSwiperStyles_titleDefault') }) { + ArcSwiper() { + Text('0') + .width(233) + .height(233) + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width(233) + .height(233) + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width(233) + .height(233) + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + } + + ComponentCard({ title: $r('app.string.ArcSwiperStyles_titleCustomize') }) { + ArcSwiper() { + Text('0') + .width(233) + .height(233) + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width(233) + .height(233) + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width(233) + .height(233) + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + .indicator( + new ArcDotIndicator() + .arcDirection(ArcDirection.SIX_CLOCK_DIRECTION) // 设置导航点位于6点钟方向 + .itemColor(Color.Red) // 设置导航点颜色为红色 + .selectedItemColor(Color.Blue) // 设置选中导航点颜色为蓝色 + ) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcSwiperStyles_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperToggle.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperToggle.ets new file mode 100644 index 0000000000000000000000000000000000000000..143dab03e084c9835a635891065543a62626a1f9 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperToggle.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 { + ArcButton, + ArcButtonOptions, + ArcButtonStatus, + ArcButtonStyleMode, + ArcButtonPosition, + ArcSwiper, + ArcSwiperAttribute, + ArcDotIndicator, + ArcDirection, + ArcSwiperController +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcSwiperToggle { + private wearableSwiperController: ArcSwiperController = new ArcSwiperController(); + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcSwiperToggle_title') }) { + Stack() { + ArcSwiper(this.wearableSwiperController) { + Text('0') + .width(233) + .height(233) + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width(233) + .height(233) + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width(233) + .height(233) + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + .vertical(true) + .indicator(false) + + Column() { + ArcButton({ + options: new ArcButtonOptions({ + label: 'previous', + position: ArcButtonPosition.TOP_EDGE, + styleMode: ArcButtonStyleMode.EMPHASIZED_LIGHT, + onClick: () => { + this.wearableSwiperController.showPrevious(); // 通过controller切换到前一页 + } + }) + }) + + Blank() + + ArcButton({ + options: new ArcButtonOptions({ + label: 'next', + position: ArcButtonPosition.BOTTOM_EDGE, + styleMode: ArcButtonStyleMode.EMPHASIZED_LIGHT, + onClick: () => { + this.wearableSwiperController.showNext(); // 通过controller切换到后一页 + } + }) + }) + }.width('100%').height('100%') + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcSwiperToggle_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperVertical.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperVertical.ets new file mode 100644 index 0000000000000000000000000000000000000000..4e27070ed8f885ad6ff9a12113450e85ffa0c8cd --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperVertical.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 { + ArcSwiper, + ArcSwiperAttribute, + ArcDotIndicator, + ArcDirection, + ArcSwiperController +} from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ArcSwiperVertical { + @State message: string = 'Hello World'; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ArcSwiperVertical_title') }) { + ArcSwiper() { + Text('0') + .width(233) + .height(233) + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width(233) + .height(233) + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width(233) + .height(233) + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + .indicator(new ArcDotIndicator() + .arcDirection(ArcDirection.THREE_CLOCK_DIRECTION)) + .vertical(true) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ArcSwiperVertical_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..98f58400da894b77fff2a7d89bdfb7767f2b6d0b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/index.ets @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ArcSwiperAction } from './ArcSwiperAction'; +import { ArcSwiperHorizontal } from './ArcSwiperHorizontal'; +import { ArcSwiperSideSlip } from './ArcSwiperSideSlip'; +import { ArcSwiperStyles } from './ArcSwiperStyles'; +import { ArcSwiperToggle } from './ArcSwiperToggle'; +import { ArcSwiperVertical } from './ArcSwiperVertical'; +import resource from '../../common/resource'; + +export const ARCSWIPER_ROUTE_PREFIX: string = 'arcSwiper'; + +const routes: Route[] = [ + { + name: `${ARCSWIPER_ROUTE_PREFIX}/ArcSwiperStyles`, + title: resource.resourceToString($r('app.string.ArcSwiperStyles_title')), + description: $r('app.string.ArcSwiperStyles_description') + }, + { + name: `${ARCSWIPER_ROUTE_PREFIX}/ArcSwiperToggle`, + title: resource.resourceToString($r('app.string.ArcSwiperToggle_title')), + description: $r('app.string.ArcSwiperToggle_description') + }, + { + name: `${ARCSWIPER_ROUTE_PREFIX}/ArcSwiperHorizontal`, + title: resource.resourceToString($r('app.string.ArcSwiperHorizontal_title')), + description: $r('app.string.ArcSwiperHorizontal_description') + }, + { + name: `${ARCSWIPER_ROUTE_PREFIX}/ArcSwiperVertical`, + title: resource.resourceToString($r('app.string.ArcSwiperVertical_title')), + description: $r('app.string.ArcSwiperVertical_description') + }, + { + name: `${ARCSWIPER_ROUTE_PREFIX}/ArcSwiperAction`, + title: resource.resourceToString($r('app.string.ArcSwiperAction_title')), + description: $r('app.string.ArcSwiperAction_description') + }, + { + name: `${ARCSWIPER_ROUTE_PREFIX}/ArcSwiperSideSlip`, + title: resource.resourceToString($r('app.string.ArcSwiperSideSlip_title')), + description: $r('app.string.ArcSwiperSideSlip_description') + } +]; + +@Builder +export function arcSwiperDestination(name: string) { + if (name === ARCSWIPER_ROUTE_PREFIX) { + ArcSwiperExample(); + } else if (name === routes[0].name) { + ArcSwiperStyles(); + } else if (name === routes[1].name) { + ArcSwiperToggle(); + } else if (name === routes[2].name) { + ArcSwiperHorizontal(); + } else if (name === routes[3].name) { + ArcSwiperVertical(); + } else if (name === routes[4].name) { + ArcSwiperAction(); + } else if (name === routes[5].name) { + ArcSwiperSideSlip(); + } +} + +@Entry +@Component +struct ArcSwiperExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('ArcSwiper', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/DataInGrid.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/DataInGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..998e35a9c3588b59688047ef09b801272c69d287 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/DataInGrid.ets @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +// [Start build_a_office_services_grid_of_foreach] +@Entry +@Component +export struct DataInGrid { + @State services: Array = ['Meeting', 'Voting', 'Check-in', 'Printing']; + + build() { + // [StartExclude build_a_office_services_grid_of_foreach] + NavDestination() { + // [EndExclude build_a_office_services_grid_of_foreach] + Column({ space: 12 }) { + // [StartExclude build_a_office_services_grid_of_foreach] + ComponentCard({ title: $r('app.string.DataInGrid_titleOfficeServices') }) { + // [EndExclude build_a_office_services_grid_of_foreach] + // [Start build_a_office_services_grid] + Grid() { + GridItem() { + Text('Meeting') + .fontSize(24) + }.backgroundColor('#FFF1F3F5') + + GridItem() { + Text('Check-in') + .fontSize(24) + }.backgroundColor('#FFF1F3F5') + + GridItem() { + Text('Voting') + .fontSize(24) + }.backgroundColor('#FFF1F3F5') + + GridItem() { + Text('Printing') + .fontSize(24) + }.backgroundColor('#FFF1F3F5') + } + // [StartExclude build_a_office_services_grid] + .height(200) + // [EndExclude build_a_office_services_grid] + .columnsGap(6) + .rowsGap(6) + .rowsTemplate('1fr 1fr') + .columnsTemplate('1fr 1fr') + // [End build_a_office_services_grid] + } + + // [StartExclude build_a_office_services_grid_of_foreach] + ComponentCard({ title: $r('app.string.DataInGrid_titleForEach') }) { + // [EndExclude build_a_office_services_grid_of_foreach] + Grid() { + ForEach(this.services, (service: string) => { + GridItem() { + Text(service) + }.backgroundColor('#FFF1F3F5') + }, (service: string): string => service) + } + // [StartExclude build_a_office_services_grid_of_foreach] + .height(200) + .columnsGap(6) + .rowsGap(6) + // [EndExclude build_a_office_services_grid_of_foreach] + .rowsTemplate(('1fr 1fr') as string) + .columnsTemplate(('1fr 1fr') as string) + } + } + // [End build_a_office_services_grid_of_foreach] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.DataInGrid_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridCalculator.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridCalculator.ets new file mode 100644 index 0000000000000000000000000000000000000000..bb1fe49ef5bb281a53c80353f9aaf1dd3324ff19 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridCalculator.ets @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct GridCalculator { + private buttonArray: string[] = + ['CE', 'C', '/', 'X', '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '=', '0', '.']; + @State res: string = '0'; + layoutOptions: GridLayoutOptions = { + regularSize: [1, 1], + onGetRectByIndex: (index: number) => { + if (index == 0) { + return [2, 0, 1, 1]; + } else if (index == 1) { + return [2, 1, 1, 1]; + } else if (index == 2) { + return [2, 2, 1, 1]; + } else if (index == 3) { + return [2, 3, 1, 1]; + } else if (index == 4) { + return [3, 0, 1, 1]; + } else if (index == 5) { + return [3, 1, 1, 1]; + } else if (index == 6) { + return [3, 2, 1, 1]; + } else if (index == 7) { + return [3, 3, 1, 1]; + } else if (index == 8) { + return [4, 0, 1, 1]; + } else if (index == 9) { + return [4, 1, 1, 1]; + } else if (index == 10) { + return [4, 2, 1, 1]; + } else if (index == 11) { + return [4, 3, 1, 1]; + } else if (index == 12) { + return [5, 0, 1, 1]; + } else if (index == 13) { + return [5, 1, 1, 1]; + } else if (index == 14) { + return [5, 2, 1, 1]; + } else if (index == 15) { + return [5, 3, 2, 1]; + } else if (index == 16) { + return [6, 0, 1, 2]; + } else if (index == 17) { + return [6, 2, 1, 1]; + } + return [0, 0, 2, 4]; + } + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.GridCalculator_title') }) { + Grid(undefined, this.layoutOptions) { + ForEach(this.buttonArray, (item: string) => { + GridItem() { + Button(item) + .width('100%') + .height('100%') + .borderRadius(10) + .backgroundColor(0x55555555) + .fontWeight(FontWeight.Bold) + .onClick(() => { + // 按钮功能实现 + // ... + }) + } + }) + GridItem() { + Text(this.res).width('100%').height('100%').textAlign(TextAlign.End).fontSize(30) + }.backgroundColor(0x55555555).borderRadius(10) + } + .columnsTemplate('1fr 1fr 1fr 1fr') + .rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr') + .rowsGap(8) + .columnsGap(5) + .width('100%') + .height('80%') + } + } + } + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridDataSource.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..f0d9e9bb8052f2cd52e3d4623f0aa6b9166707ae --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridDataSource.ets @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class GridDataSource implements IDataSource { + private list: string[] = []; + private listeners: DataChangeListener[] = []; + + constructor(list: string[]) { + this.list = list; + } + + totalCount(): number { + return this.list.length; + } + + getData(index: number): string { + return this.list[index]; + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener); + } + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + // 通知控制器数据位置变化 + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }) + } + + // 交换元素位置 + public swapItem(from: number, to: number): void { + let temp: string = this.list[from]; + this.list[from] = this.list[to]; + this.list[to] = temp; + this.notifyDataMove(from, to); + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridLayout.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridLayout.ets new file mode 100644 index 0000000000000000000000000000000000000000..464b10d7282f3dc3b451609145686325b01240cf --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridLayout.ets @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct GridLayout { + @State numbers: String[] = ['0', '1', '2', '3', '4', '5', '6', '7']; + scroller: Scroller = new Scroller(); + // [Start set_rows_and_columns_occupied] + layoutOptions: GridLayoutOptions = { + regularSize: [1, 1], + irregularIndexes: [1, 3, 4], // 索引为0和7的GridItem占用的列数由onGetIrregularSizeByIndex指定 + onGetIrregularSizeByIndex: (index: number) => { + if (index === 0) { + return [1, 5]; + } + return [1, index % 6 + 1]; + } + } + + // [StartExclude set_rows_and_columns_occupied] + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.GridLayout_titleRowSpacing') }) { + // [EndExclude set_rows_and_columns_occupied] + // [Start build_a_grid] + Grid() { + // [StartExclude build_a_grid] + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + + GridItem() { + }.backgroundColor('#ffe0e2e4') + // [EndExclude build_a_grid] + } + //设置行列间距 + // [StartExclude build_a_grid] + .columnsGap(10) + .rowsGap(15) + .height(150) + // [EndExclude build_a_grid] + //设置行列数量与占比 + .rowsTemplate('1fr 1fr 1fr') + .columnsTemplate('1fr 2fr 1fr') + // [End build_a_grid] + // [End set_rows_and_columns_occupied] + } + + ComponentCard({ title: $r('app.string.GridLayout_titleChildSpan') }) { + Grid(undefined, this.layoutOptions) { + ForEach(this.numbers, (day: string) => { + GridItem() { + Text(day) + .fontSize(16) + .backgroundColor('#ffe0e2e4') + .width('100%') + .height(60) + .textAlign(TextAlign.Center) + } + }, (day: string) => day) + } + .columnsTemplate('1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + .scrollBar(BarState.Off) + .width('80%') + .height(210) + } + + ComponentCard({ title: $r('app.string.GridLayout_titleMainAxis') }) { + // [Start Set_the_direction_of_the_main_axis_of_the_grid] + Grid() { + // [StartExclude Set_the_direction_of_the_main_axis_of_the_grid] + GridItem() { + Text('1') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('2') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('3') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('4') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('5') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('6') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('7') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('8') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('9') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + // [EndExclude Set_the_direction_of_the_main_axis_of_the_grid] + } + .maxCount(3) + // [StartExclude Set_the_direction_of_the_main_axis_of_the_grid] + .columnsGap(4) + .rowsGap(4) + // [EndExclude Set_the_direction_of_the_main_axis_of_the_grid] + .layoutDirection(GridDirection.Row) + // [End Set_the_direction_of_the_main_axis_of_the_grid] + + Grid() { + GridItem() { + Text('1') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('2') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('3') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('4') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('5') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('6') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('7') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('8') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + + GridItem() { + Text('9') + }.backgroundColor('#ffe0e2e4').width(30).height(30) + } + .maxCount(3) + .columnsGap(4) + .rowsGap(4) + .layoutDirection(GridDirection.Column) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.GridLayout_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridScrollbar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridScrollbar.ets new file mode 100644 index 0000000000000000000000000000000000000000..74443ede7231b3c0ef3b7f976a730a51cb05e45c --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridScrollbar.ets @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { GridDataSource } from './GridDataSource'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct GridScrollbar { + numbers: GridDataSource = new GridDataSource([]); + scroller: Scroller = new Scroller(); + @State gridPosition: number = 0; //0代表滚动到grid顶部,1代表中间值,2代表滚动到grid底部。 + + aboutToAppear() { + let list: string[] = []; + for (let i = 0; i < 5; i++) { + for (let j = 0; j < 5; j++) { + list.push(j.toString()); + } + } + this.numbers = new GridDataSource(list); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.GridScrollbar_title') }) { + Row({ space: 5 }) { + Grid(this.scroller) { + LazyForEach(this.numbers, (day: string) => { + GridItem() { + Text() + .fontSize(16) + .backgroundColor(0xF9CF93) + .width('100%') + .height(80) + .textAlign(TextAlign.Center) + } + }, (index: number) => index.toString()) + } + .columnsTemplate('1fr 1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + .friction(0.6) + .enableScrollInteraction(true) + .supportAnimation(false) + .multiSelectable(false) + .edgeEffect(EdgeEffect.Spring) + .scrollBar(BarState.Off) + .scrollBarColor(Color.Grey) + .scrollBarWidth(4) + .width('90%') + .backgroundColor(0xFAEEE0) + .height(300) + .margin({left:10}) + ScrollBar({ scroller: this.scroller }).height(300) + + }.width('100%').margin({ top: 5 }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.GridScrollbar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridSideToSide.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridSideToSide.ets new file mode 100644 index 0000000000000000000000000000000000000000..fd30401da34682d2b17f44b8411c2cb5d81de55a --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/GridSideToSide.ets @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { GridDataSource } from './GridDataSource'; +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct GridSideToSide { + numbers: GridDataSource = new GridDataSource([]); + scroller: Scroller = new Scroller(); + @State gridPosition: number = 0; //0代表滚动到grid顶部,1代表中间值,2代表滚动到grid底部。 + @State data: number = 1; + + aboutToAppear() { + let list: string[] = []; + for (let i = 0; i < 7; i++) { + for (let j = 0; j < 10; j++) { + list.push(this.data.toString()); + this.data += 1; + if(this.data == 32) { + this.data = 0; + } + } + } + this.numbers = new GridDataSource(list); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.GridSideToSide_title') }) { + Column(){ + Grid(this.scroller) { + LazyForEach(this.numbers, (day: string) => { + GridItem() { + Text(day) + .fontSize(16) + .backgroundColor(0xF9CF93) + .width('100%') + .height(50) + .textAlign(TextAlign.Center) + } + }, (index: number) => index.toString()) + } + .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + .width('90%') + .height(300) + .scrollBar(BarState.Off) + + Row({ space: 20 }) { + Button('上一页') + .onClick(() => { + this.scroller.scrollPage({ + next: false + }); + }) + + Button('下一页') + .onClick(() => { + this.scroller.scrollPage({ + next: true + }); + }) + } + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.GridSideToSide_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/LongGrid.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/LongGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..073655c3e3024bba52fa4496f8f9ece2e03c2774 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/LongGrid.ets @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; +import { GridDataSource } from './GridDataSource'; + +@Entry +@Component +export struct LongGrid { + numbers: GridDataSource = new GridDataSource([]); + scroller: Scroller = new Scroller(); + + aboutToAppear() { + let list: string[] = []; + for (let i = 0; i <= 10; i++) { + for (let j = 0; j < 5; j++) { + list.push(j.toString()); + } + } + this.numbers = new GridDataSource(list); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.LongGrid_title') }) { + Column({ space: 5 }) { + Grid(this.scroller) { + LazyForEach(this.numbers, (day: string) => { + GridItem() { + Text(day) + .fontSize(16) + .backgroundColor(0xF9CF93) + .width('100%') + .height(80) + .textAlign(TextAlign.Center) + } + }, (index: number) => index.toString()) + } + .columnsTemplate('1fr 1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(20) + .edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true, effectEdge: EffectEdge.START }) + .width('90%') + .backgroundColor(0xDCDCDC) + .height('80%') + + }.width('100%').margin({ top: 5 }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.LongGrid_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/ScrollPositionGrid.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/ScrollPositionGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..da773f1c37ed27e85c02d98ec3db72585f7fa335 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/ScrollPositionGrid.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ScrollPosition { + @State services: Array = ['Live Streaming', 'Imported', 'Categories', 'Recharge', + 'Membership', 'Claim Coupon', 'Lottery', 'Favorites', 'Points', 'More']; + // [Start build_a_private_scrolling_object] + private scroller: Scroller = new Scroller(); + // [End build_a_private_scrolling_object] + + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ScrollPosition_titleExample') }) { + // [Start control_the_grid_scroll] + Column({ space: 12 }) { + Grid(this.scroller) { + // [StartExclude control_the_grid_scroll] + ForEach(this.services, (service: string) => { + GridItem() { + Text(service) + }.backgroundColor('#FFF1F3F5').width('25%') + }, (service: string): string => service) + // [EndExclude control_the_grid_scroll] + } + // [StartExclude control_the_grid_scroll] + .height(100) + .columnsGap(10) + // [EndExclude control_the_grid_scroll] + .rowsTemplate('1fr') + + Row({ space: 20 }) { + Button('Previous') + .onClick(() => { + this.scroller.scrollPage({ next: false }); + }) + + Button('Next') + .onClick(() => { + this.scroller.scrollPage({ next: true }); + }) + } + } + // [End control_the_grid_scroll] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ScrollPosition_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/ScrollableGrid.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/ScrollableGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..288ed72065440598d7edf5a99e8c68c7e4bfde69 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/ScrollableGrid.ets @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +// [Start build_scrollable_horizontally_grid_layouts] +@Entry +@Component +export struct ScrollableGrid { + @State services: Array = ['Live Streaming', 'Imported', 'Categories', 'Recharge', + 'Membership', 'Claim Coupon', 'Lottery', 'Favorites', 'Points', 'More']; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ScrollableGrid_titleHorizontal') }) { + Grid() { + ForEach(this.services, (service: string) => { + GridItem() { + Text(service) + }.backgroundColor('#FFF1F3F5').width('25%') + }, (service: string): string => service) + } + // [StartExclude build_scrollable_horizontally_grid_layouts] + .height(200) + .columnsGap(10) + // [EndExclude build_scrollable_horizontally_grid_layouts] + .rowsGap(15) + .rowsTemplate('1fr 1fr') // 只设置rowsTemplate属性,当内容超出Grid区域时,可水平滚动。 + } + } + // [End build_scrollable_horizontally_grid_layouts] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ScrollableGrid_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..cc39def6cb82479ef34d99f0ffd76a7c741732d6 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { DataInGrid } from './DataInGrid'; +import { GridLayout } from './GridLayout'; +import { Route } from '../../common/Route'; +import { ScrollableGrid } from './ScrollableGrid'; +import { ScrollPosition } from './ScrollPositionGrid'; +import { GridSideToSide } from './GridSideToSide'; +import { GridScrollbar } from './GridScrollbar'; +import { LongGrid } from './LongGrid'; +import { GridCalculator } from './GridCalculator'; +import resource from '../../common/resource'; + +export const GRID_ROUTE_PREFIX: string = 'grid'; + +const routes: Route[] = [ + { + name: `${GRID_ROUTE_PREFIX}/GridLayout`, + title: resource.resourceToString($r('app.string.GridLayout_title')), + description: $r('app.string.GridLayout_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/DataInGrid`, + title: resource.resourceToString($r('app.string.DataInGrid_title')), + description: $r('app.string.DataInGrid_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/ScrollableGrid`, + title: resource.resourceToString($r('app.string.ScrollableGrid_title')), + description: $r('app.string.ScrollableGrid_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/ScrollPosition`, + title: resource.resourceToString($r('app.string.ScrollPosition_title')), + description: $r('app.string.ScrollPosition_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/GridSideToSide`, + title: resource.resourceToString($r('app.string.GridSideToSide_title')), + description: $r('app.string.GridSideToSide_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/GridScrollbar`, + title: resource.resourceToString($r('app.string.GridScrollbar_title')), + description: $r('app.string.GridScrollbar_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/LongGrid`, + title: resource.resourceToString($r('app.string.LongGrid_title')), + description: $r('app.string.LongGrid_description') + }, + { + name: `${GRID_ROUTE_PREFIX}/GridCalculator`, + title: resource.resourceToString($r('app.string.GridCalculator_title')), + description: $r('app.string.GridCalculator_description') + } +]; + +@Builder +export function gridDestination(name: string) { + if (name === GRID_ROUTE_PREFIX) { + GridExample(); + } else if (name === routes[0].name) { + GridLayout(); + } else if (name === routes[1].name) { + DataInGrid(); + } else if (name === routes[2].name) { + ScrollableGrid(); + } else if (name === routes[3].name) { + ScrollPosition(); + } else if (name === routes[4].name) { + GridSideToSide(); + } else if (name === routes[5].name) { + GridScrollbar(); + } else if (name === routes[6].name) { + LongGrid(); + } else if (name === routes[7].name) { + GridCalculator(); + } +} + +@Entry +@Component +struct GridExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('Grid', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/AddListItem.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/AddListItem.ets new file mode 100644 index 0000000000000000000000000000000000000000..befa4ca236b5c617a222d87786323ebb9fbb7cd9 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/AddListItem.ets @@ -0,0 +1,154 @@ + /* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; +// [Start define_the_data_to_be_done] +import { util } from '@kit.ArkTS'; + + +export class ToDo { + public key: string = util.generateRandomUUID(true); + public name: string; + + constructor(name: string) { + this.name = name; + } +} +// [End define_the_data_to_be_done] + +// [Start build_the_overall_list_layout_and_list_items] +@Component +export struct ToDoListItem { + @Link isEditMode: boolean; + @Link selectedItems: ToDo[]; + private toDoItem: ToDo = new ToDo(''); + + build() { + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + // [StartExclude build_the_overall_list_layout_and_list_items] + Text(this.toDoItem.name) + .fontSize(16) + .width('80%') + .margin({ left: 20 }) + // [EndExclude build_the_overall_list_layout_and_list_items] + } + .backgroundColor('#FFF1F3F5') + .width('100%') + .height(40) + // .padding() 根据具体使用场景设置 + .borderRadius(12) + // .linearGradient() 根据具体使用场景设置 + .gesture( + // [StartExclude build_the_overall_list_layout_and_list_items] + GestureGroup(GestureMode.Exclusive, + LongPressGesture() + // [EndExclude build_the_overall_list_layout_and_list_items] + .onAction(() => { + }) + ) + ) + } +} +// [End build_the_overall_list_layout_and_list_items] + +// [Start build_list_layouts_and_list_items] +@Entry +@Component +export struct AddListItem { + private l1 = 0; + private l2 = 0; + // [StartExclude build_list_layouts_and_list_items] + @State arr: number[] = [0, 1, 2, 3] + @State toDoData: ToDo[] = [] + // [EndExclude build_list_layouts_and_list_items] + @Watch('onEditModeChange') @State isEditMode: boolean = false + @State selectedItems: ToDo[] = [] + private availableThings: string[] = ['Reading', 'Exercise', 'Travel', 'Listening Music', 'Watching Films', 'Singing']; + + onEditModeChange() { + if (!this.isEditMode) { + this.selectedItems = []; + } + } + + build() { + // [StartExclude build_list_layouts_and_list_items] + NavDestination() { + // [EndExclude build_list_layouts_and_list_items] + Column({ space: 12 }) { + // [StartExclude build_list_layouts_and_list_items] + ComponentCard({ title: $r('app.string.AddListItem_titleExample') }) { + // [EndExclude build_list_layouts_and_list_items] + Column({ space: 12 }) { + Row() { + if (this.isEditMode) { + Text('X') + .fontSize(20) + .onClick(() => { + this.isEditMode = false; + }) + .margin({ left: 20, right: 20 }) + } else { + Text($r('app.string.TodoItem')) + .fontSize(30) + .margin({ left: 20 }) + Blank() + Text('+')// 提供新增列表项入口,即给新增按钮添加点击事件 + .fontSize(36) + .margin({ right: 20 }) + .onClick(() => { + this.getUIContext().showTextPickerDialog({ + range: this.availableThings, + onAccept: (value: TextPickerResult) => { + let arr = Array.isArray(value.index) ? value.index : [value.index]; + for (let i = 0; i < arr.length; i++) { + this.toDoData.push(new ToDo(this.availableThings[arr[i]])); // 新增列表项数据toDoData(可选事项) + } + }, + }) + }) + } + } + // [StartExclude build_list_layouts_and_list_items] + .width('100%') + .backgroundColor('#FFF1F3F5') + .borderRadius(12) + .height(45) + // [EndExclude build_list_layouts_and_list_items] + + List({ space: 12 }) { + ForEach(this.toDoData, (toDoItem: ToDo) => { + ListItem() { + // 将toDoData的每个数据放入到以model的形式放进ListItem里 + ToDoListItem({ + isEditMode: this.isEditMode, + toDoItem: toDoItem, + selectedItems: this.selectedItems + }) + } + }, (toDoItem: ToDo) => toDoItem.name.toString()) + } + } + } + } + // [End build_list_layouts_and_list_items] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.AddListItem_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/CollapseAndExpand.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/CollapseAndExpand.ets new file mode 100644 index 0000000000000000000000000000000000000000..52fd69387c7086e8b86b6aff6b4e075f119a6f3b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/CollapseAndExpand.ets @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { curves } from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + +interface ItemInfo { + index: number, + name: string, + label: ResourceStr, + type?: string, +} + +interface ItemGroupInfo extends ItemInfo { + children: ItemInfo[] +} + + +@Entry +@Component +export struct CollapseAndExpand { + @State routes: ItemGroupInfo[] = [ + { + index: 0, + name: 'basicInfo', + label: '个人基本资料', + children: [ + { + index: 0, + name: '昵称', + label: 'xxxx', + type: 'Text' + }, + { + index: 1, + name: '头像', + label: $r('sys.media.ohos_user_auth_icon_face'), + type: 'Image' + }, + { + index: 2, + name: '年龄', + label: 'xxxx', + type: 'Text' + }, + { + index: 3, + name: '生日', + label: 'xxxxxxxxx', + type: 'Text' + }, + { + index: 4, + name: '性别', + label: 'xxxxxxxx', + type: 'Text' + }, + ] + }, + { + index: 1, + name: 'equipInfo', + label: '设备信息', + children: [] + }, + { + index: 2, + name: 'appInfo', + label: '应用使用信息', + children: [] + }, + { + index: 3, + name: 'uploadInfo', + label: '您主动上传的数据', + children: [] + }, + { + index: 4, + name: 'tradeInfo', + label: '交易与资产信息', + children: [] + }, + { + index: 5, + name: 'otherInfo', + label: '其他资料', + children: [] + }, + ]; + + @State expandedItems: boolean[] = Array(this.routes.length).fill(false); + @State selection: string | null = null; + + @Builder + ListItemGroupHeader(itemGroup: ItemGroupInfo) { + Row() { + Text(itemGroup.label) + Blank() + Image($r('sys.media.ohos_ic_public_arrow_down')) + .fillColor($r('sys.color.ohos_id_color_fourth')) + .height(30) + .width(30) + .rotate({ angle: !!itemGroup.children.length ? (this.expandedItems[itemGroup.index] ? 180 : 0) : 180 }) + .animation({ curve: curves.interpolatingSpring(0, 1, 228, 22) }) + } + .width("100%") + .padding(10) + .animation({ curve: curves.interpolatingSpring(0, 1, 528, 39) }) + .onClick(() => { + if (itemGroup.children.length) { + this.getUIContext()?.animateTo({ curve: curves.interpolatingSpring(0, 1, 528, 39) }, () => { + this.expandedItems[itemGroup.index] = !this.expandedItems[itemGroup.index]; + }) + } + }) + } + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.CollapseAndExpand_title') }) { + Column() { + List({ space: 10 }) { + ForEach(this.routes, (itemGroup: ItemGroupInfo) => { + ListItemGroup({ + header: this.ListItemGroupHeader(itemGroup), + style: ListItemGroupStyle.CARD, + }) { + if (this.expandedItems[itemGroup.index] && itemGroup.children) { + ForEach(itemGroup.children, (item: ItemInfo) => { + ListItem({ style: ListItemStyle.CARD }) { + Row() { + Text(item.name) + Blank() + if (item.type === 'Image') { + Image(item.label) + .height(20) + .width(20) + } else { + Text(item.label) + } + Image($r('sys.media.ohos_ic_public_arrow_right')) + .fillColor($r('sys.color.ohos_id_color_fourth')) + .height(30) + .width(30) + } + .width("100%") + } + .width("100%") + .animation({ curve: curves.interpolatingSpring(0, 1, 528, 39) }) + }) + } + }.clip(true) + }) + } + .width("100%") + } + .width('100%') + .height('100%') + .justifyContent(FlexAlign.Start) + .backgroundColor($r('sys.color.ohos_id_color_sub_background')) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CollapseAndExpand_title')) + } + +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ControlledScrollPositionList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ControlledScrollPositionList.ets new file mode 100644 index 0000000000000000000000000000000000000000..fe9700cfd7503197f185a9d8299472e3644df987 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ControlledScrollPositionList.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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ControlledScrollPositionList { + // [Start create_private_list_scroller] + private listScroller: Scroller = new Scroller(); + // [End create_private_list_scroller] + private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ControlledScrollPositionList_titleExample') }) { + // [Start control_scrolling] + Stack({ alignContent: Alignment.Bottom }) { + // 控制滚动位置示例List容器 + // 将listScroller用于初始化List组件的scroller参数,完成listScroller与列表的绑定。 + List({ space: 20, scroller: this.listScroller }) { + // ... + // [StartExclude control_scrolling] + ForEach(this.arr, (item: number) => { + ListItem() { + Text('新闻' + item) + .width('100%') + .height(100) + .fontSize(16) + .textAlign(TextAlign.Center) + .borderRadius(10) + .backgroundColor('#FFF1F3F5') + } + }, (item: number) => item.toString()) + // [EndExclude control_scrolling] + } + + Button() { + // [StartExclude control_scrolling] + // ... + Image($r('sys.media.ohos_ic_public_arrow_up')).width(40).height(40) + // [EndExclude control_scrolling] + } + // [StartExclude control_scrolling] + .backgroundColor('#FFE0E2E4') + .position({ x: '80%', y: '90%' }) + // [EndExclude control_scrolling] + .onClick(() => { + // 点击按钮时,指定跳转位置,返回列表顶部 + this.listScroller.scrollToIndex(0); + // [End control_scrolling] + }) + }.height('90%') + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ControlledScrollPositionList_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/CustomListStyle.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/CustomListStyle.ets new file mode 100644 index 0000000000000000000000000000000000000000..b61ca2a29c1f41a54f6638615764c5f3f50ec91b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/CustomListStyle.ets @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +// [Start set_the_divider] +class DividerTmp { + public strokeWidth: Length = 1; + public startMargin: Length = 60; + public endMargin: Length = 10; + public color: ResourceColor = '#ffe9f0f0'; + + constructor(strokeWidth: Length, startMargin: Length, endMargin: Length, color: ResourceColor) { + this.strokeWidth = strokeWidth; + this.startMargin = startMargin; + this.endMargin = endMargin; + this.color = color; + } +} + +@Entry +@Component +export struct CustomListStyle { + @State egDivider: DividerTmp = new DividerTmp(1, 60, 10, '#ffe9f0f0'); + + build() { + // [StartExclude set_the_divider] + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.CustomListStyle_titleContentSpacing') }) { + List({ space: 10 }) { + ListItem() { + Text('ListItem One') + } + + ListItem() { + Text('ListItem Two') + } + } + .backgroundColor('#FFF1F3F5') + .alignListItem(ListItemAlign.Center) + } + + ComponentCard({ title: $r('app.string.CustomListStyle_titleDividerLines') }) { + // [EndExclude set_the_divider] + List({ space: 10 }) { + ListItem() { + Text('ListItem One') + } + + ListItem() { + Text('ListItem Two') + } + } + .divider(this.egDivider) + .alignListItem(ListItemAlign.Center) + } + // [End set_the_divider] + + ComponentCard({ title: $r('app.string.CustomListStyle_titleScrollbars') }) { + // [Start add_a_scrollbar] + List({ space: 10 }) { + // [StartExclude add_a_scrollbar] + ListItem() { + Text('ListItem One') + }.height(30) + + ListItem() { + Text('ListItem Two') + }.height(30) + + ListItem() { + Text('ListItem Three') + }.height(30) + // [EndExclude add_a_scrollbar] + } + // [StartExclude add_a_scrollbar] + .height(60) + // [EndExclude add_a_scrollbar] + .scrollBar(BarState.Auto) + // [End add_a_scrollbar] + .backgroundColor('#FFF1F3F5') + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomListStyle_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/DataInList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/DataInList.ets new file mode 100644 index 0000000000000000000000000000000000000000..1a4832087e576b0a12b577a4543e482469b5dde2 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/DataInList.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. + */ + +import { ComponentCard } from '../../common/Card'; + +// [Start list_statically_creates_the_contents_of_list_item] +@Entry +@Component +export struct DataInList { + build() { + // [StartExclude list_statically_creates_the_contents_of_list_item] + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.DataInList_titleCityList') }) { + // [EndExclude list_statically_creates_the_contents_of_list_item] + List() { + ListItem() { + Text($r('app.string.city_beijing')) + .fontSize(24) + } + + ListItem() { + Text($r('app.string.city_hangzhou')) + .fontSize(24) + } + + ListItem() { + Text($r('app.string.city_shanghai')) + .fontSize(24) + } + } + .backgroundColor('#FFF1F3F5') + .alignListItem(ListItemAlign.Center) + } + // [End list_statically_creates_the_contents_of_list_item] + + ComponentCard({ title: $r('app.string.DataInList_titleContactsList') }) { + // [Start encapsulate_the_image_and_text_into_a_row] + List() { + ListItem() { + Row() { + Image($r('sys.media.ohos_ic_public_phone')) + .width(40) + .height(40) + .margin(10) + + Text($r('app.string.peopleOne')) + .fontSize(20) + } + } + + ListItem() { + Row() { + Image($r('sys.media.ohos_ic_public_phone')) + .width(40) + .height(40) + .margin(10) + + Text($r('app.string.peopleTwo')) + .fontSize(20) + } + } + } + } + } + // [End encapsulate_the_image_and_text_into_a_row] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.DataInList_titlePage')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/DeleteListItem.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/DeleteListItem.ets new file mode 100644 index 0000000000000000000000000000000000000000..6948f3a13eb5a1a4fe63646227f8f51bf42ac8fa --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/DeleteListItem.ets @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { util } from '@kit.ArkTS'; + +// [Start structural_references] +export class ToDo { + public key: string = util.generateRandomUUID(true); + public name: string; + + constructor(name: string) { + this.name = name; + } +} +// [End structural_references] + +@Component +export struct ToDoListItem { + @Link isEditMode: boolean; + @Link selectedItems: ToDo[]; + private toDoItem: ToDo = new ToDo(''); + + build() { + // [Start enter_edit_mode] + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + // [StartExclude enter_edit_mode] + Text(this.toDoItem.name) + .fontSize(16) + .width('80%') + .margin({ left: 20 }) + if (this.isEditMode) { + Checkbox() + .onChange((value: boolean) => { + if (value) { + this.selectedItems.push(new ToDo(this.toDoItem.name)); + this.isEditMode = true; + } + }) + } + } + .backgroundColor('#FFF1F3F5') + .width('100%') + .height(40) + .borderRadius(12) + // [EndExclude enter_edit_mode] + .gesture( + GestureGroup(GestureMode.Exclusive, + LongPressGesture() + .onAction(() => { + this.isEditMode = true; + }) + ) + ) + } +} +// [End enter_edit_mode] + +@Entry +@Component +export struct DeleteListItem { + @State arr: number[] = [0, 1, 2, 3]; + @State toDoData: ToDo[] = []; + @Watch('onEditModeChange') @State isEditMode: boolean = false; + @State selectedItems: ToDo[] = []; + private availableThings: string[] = ['Reading', 'Exercise', 'Travel', 'Listening Music', 'Watching Films', 'Singing']; + + public deleteToDoData() { + this.toDoData = []; + } + + onEditModeChange() { + if (!this.isEditMode) { + this.selectedItems = []; + } + } + + build() { + NavDestination() { + Column({ space: 12 }) { + Column({ space: 8 }) { + Text($r('app.string.DeleteListItem_titleExample')) + .fontSize(14) + .fontColor('#666') + Column({ space: 10 }) { + Row() { + if (this.isEditMode) { + Text('X') + .fontSize(20) + .onClick(() => { + this.isEditMode = false; + }) + .margin({ left: 20, right: 20 }) + } else { + Text($r('app.string.TodoItem')) + .fontSize(30) + .margin({ left: 20 }) + Blank() + Text('+')// 提供新增列表项入口,即给新增按钮添加点击事件 + .fontSize(36) + .margin({ right: 20 }) + .onClick(() => { + this.getUIContext().showTextPickerDialog({ + range: this.availableThings, + onAccept: (value: TextPickerResult) => { + let arr = Array.isArray(value.index) ? value.index : [value.index]; + for (let i = 0; i < arr.length; i++) { + this.toDoData.push(new ToDo(this.availableThings[arr[i]])); // 新增列表项数据toDoData(可选事项) + } + }, + }) + }) + } + } + .width('100%') + .backgroundColor('#FFF1F3F5') + .borderRadius(12) + .height(45) + + List({ space: 12 }) { + ForEach(this.toDoData, (toDoItem: ToDo) => { + ListItem() { + // 将toDoData的每个数据放入到以model的形式放进ListItem里 + ToDoListItem({ + isEditMode: this.isEditMode, + toDoItem: toDoItem, + selectedItems: this.selectedItems + }) + } + }, (toDoItem: ToDo) => toDoItem.name.toString()) + } + } + } + .alignItems(HorizontalAlign.Start) + .backgroundColor('#fff') + .borderRadius(12) + .padding(12) + .width('100%') + + if (this.isEditMode) { + Column({ space: 8 }) { + // [Start implement_deletion] + Button('delete') + .width('90%') + .backgroundColor(Color.Red) + .onClick(() => { + this.toDoData = this.toDoData.filter(toDoItem => + !this.selectedItems.some(selectedItem => selectedItem.name === toDoItem.name)); + this.isEditMode = false; + }) + } + } + } + // [End implement_deletion] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.DeleteListItem_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/GroupedList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/GroupedList.ets new file mode 100644 index 0000000000000000000000000000000000000000..8bae8f53c90c81997957585aca9c3aefca5119f0 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/GroupedList.ets @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +// [Start set_the_head_component_of_the_list_grouping_by_header] +@Entry +@Component +export struct GroupedList { + @Builder + itemHead(text: string) { + // 列表分组的头部组件,对应联系人分组A、B等位置的组件 + Text(text) + .fontSize(20) + .backgroundColor('#fff1f3f5') + .width('100%') + .padding(5) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.GroupedList_titleExample') }) { + List({ space: 12 }) { + ListItemGroup({ header: this.itemHead('A') }) { + // 循环渲染分组A的ListItem + // [StartExclude set_the_head_component_of_the_list_grouping_by_header] + ListItem() { + Text('ListItem A One') + } + + ListItem() { + Text('ListItem A Two') + } + // [EndExclude set_the_head_component_of_the_list_grouping_by_header] + } + + ListItemGroup({ header: this.itemHead('B') }) { + // 循环渲染分组B的ListItem + // [StartExclude set_the_head_component_of_the_list_grouping_by_header] + ListItem() { + Text('ListItem B One') + } + + ListItem() { + Text('ListItem B Two') + } + // [EndExclude set_the_head_component_of_the_list_grouping_by_header] + } + } + } + } + // [End set_the_head_component_of_the_list_grouping_by_header] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.GroupedList_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..fbc9b904b59bc686e7158a4b6355c0c8091880cd --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { AddListItem } from './AddListItem'; +import { CompletedRoutableCard } from '../../common/Card'; +import { ControlledScrollPositionList } from './ControlledScrollPositionList'; +import { CustomListStyle } from './CustomListStyle'; +import { DataInList } from './DataInList'; +import { DeleteListItem } from './DeleteListItem'; +import { GroupedList } from './GroupedList'; +import { ListIteration } from './ListIteration'; +import { ListLayout } from './ListLayout'; +import { ResponsiveScrollPositionList } from './ResponsiveScrollPositionList'; +import { Route } from '../../common/Route'; +import { StickyHeaderList } from './StickyHeaderList'; +import { SwipeListItem } from './SwipeableListItem'; +import { TaggedListItems } from './TaggedListItems'; +import { CollapseAndExpand } from './CollapseAndExpand'; +import { LongList } from './LongList'; +import { ListChatRoom } from './ListChatRoom'; +import resource from '../../common/resource'; + +export const List_ROUTE_PREFIX: string = 'list'; + +const routes: Route[] = [ + { + name: `${List_ROUTE_PREFIX}/ListLayout`, + title: resource.resourceToString($r('app.string.ListLayout_title')), + description: $r('app.string.ListLayout_description') + }, + { + name: `${List_ROUTE_PREFIX}/DataInList`, + title: resource.resourceToString($r('app.string.DataInList_title')), + description: $r('app.string.DataInList_description') + }, + { + name: `${List_ROUTE_PREFIX}/ListIteration`, + title: resource.resourceToString($r('app.string.ListIteration_title')), + description: $r('app.string.ListIteration_description') + }, + { + name: `${List_ROUTE_PREFIX}/CustomListStyle`, + title: resource.resourceToString($r('app.string.CustomListStyle_title')), + description: $r('app.string.CustomListStyle_description') + }, + { + name: `${List_ROUTE_PREFIX}/GroupedList`, + title: resource.resourceToString($r('app.string.GroupedList_title')), + description: $r('app.string.GroupedList_description') + }, + { + name: `${List_ROUTE_PREFIX}/StickyHeaderList`, + title: resource.resourceToString($r('app.string.StickyHeaderList_title')), + description: $r('app.string.StickyHeaderList_description') + }, + { + name: `${List_ROUTE_PREFIX}/ControlledScrollPositionList`, + title: resource.resourceToString($r('app.string.ControlledScrollPositionList_title')), + description: $r('app.string.ControlledScrollPositionList_description') + }, + { + name: `${List_ROUTE_PREFIX}/ResponsiveScrollPositionList`, + title: resource.resourceToString($r('app.string.ResponsiveScrollPositionList_title')), + description: $r('app.string.ResponsiveScrollPositionList_description') + }, + { + name: `${List_ROUTE_PREFIX}/SwipeListItem`, + title: resource.resourceToString($r('app.string.SwipeListItem_title')), + description: $r('app.string.SwipeListItem_description') + }, + { + name: `${List_ROUTE_PREFIX}/TaggedListItems`, + title: resource.resourceToString($r('app.string.TaggedListItems_title')), + description: $r('app.string.TaggedListItems_description') + }, + { + name: `${List_ROUTE_PREFIX}/AddListItem`, + title: resource.resourceToString($r('app.string.AddListItem_title')), + description: $r('app.string.AddListItem_description') + }, + { + name: `${List_ROUTE_PREFIX}/DeleteListItem`, + title: resource.resourceToString($r('app.string.DeleteListItem_title')), + description: $r('app.string.DeleteListItem_description') + }, + { + name: `${List_ROUTE_PREFIX}/LongList`, + title: resource.resourceToString($r('app.string.LongList_title')), + description: $r('app.string.LongList_description') + }, + { + name: `${List_ROUTE_PREFIX}/CollapseAndExpand`, + title: resource.resourceToString($r('app.string.CollapseAndExpand_title')), + description: $r('app.string.CollapseAndExpand_description') + }, + { + name: `${List_ROUTE_PREFIX}/ListChatRoom`, + title: resource.resourceToString($r('app.string.ListChatRoom_title')), + description: $r('app.string.ListChatRoom_description') + } +]; + +@Builder +export function listDestination(name: string) { + if (name === List_ROUTE_PREFIX) { + ListExample(); + } else if (name === routes[0].name) { + ListLayout(); + } else if (name === routes[1].name) { + DataInList(); + } else if (name === routes[2].name) { + ListIteration(); + } else if (name === routes[3].name) { + CustomListStyle(); + } else if (name === routes[4].name) { + GroupedList(); + } else if (name === routes[5].name) { + StickyHeaderList(); + } else if (name === routes[6].name) { + ControlledScrollPositionList(); + } else if (name === routes[7].name) { + ResponsiveScrollPositionList(); + } else if (name === routes[8].name) { + SwipeListItem(); + } else if (name === routes[9].name) { + TaggedListItems(); + } else if (name === routes[10].name) { + AddListItem(); + } else if (name === routes[11].name) { + DeleteListItem(); + } else if (name === routes[12].name) { + LongList(); + } else if (name === routes[13].name) { + CollapseAndExpand(); + } else if (name === routes[14].name) { + ListChatRoom(); + } +} + +@Entry +@Component +struct ListExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('List', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListChatRoom.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListChatRoom.ets new file mode 100644 index 0000000000000000000000000000000000000000..f71e5b69ea6f1359b877688bee7de8f97092fe9f --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListChatRoom.ets @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card' +// 消息类型定义 +interface Message { + id: number + content: string + sender: string +} + +@Entry +@Component +export struct ListChatRoom { + // 自定义消息组件 + @Builder + MessageItem(message: Message) { + Column() { + Text(`${message.sender}: ${message.content}`) + .fontSize(16) + .textAlign(TextAlign.Start) + .padding(10) + .backgroundColor(message.sender === '系统' ? '#F0F0F0' : '#E6F3FF') + .borderRadius(8) + } + .width('100%') + .alignItems(HorizontalAlign.Start) + .margin({ bottom: 8 }) + } + + // 发送消息方法 + sendMessage() { + if (this.inputText.trim()) { + this.messages = [...this.messages, { + id: Date.now(), + content: this.inputText, + sender: '观众' + }] + this.inputText = '' + } + } + // 消息列表数据 + @State messages: Message[] = [ + { id: 1, content: '欢迎来到直播间!', sender: '系统' }, + { id: 2, content: '大家好啊~', sender: '主播' } + ] + + // 输入框内容 + @State inputText: string = '' + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ListChatRoom_title') }) { + Column() { + // 聊天消息区域 + List({ space: 10 }) { + ForEach(this.messages, (item: Message) => { + ListItem() { + this.MessageItem(item) + } + }, (item: Message) => item.id.toString()) + } + .layoutWeight(1) // 占据剩余空间 + .alignListItem(ListItemAlign.Center) + + // 输入区域 + Row({ space: 10 }) { + TextInput({ text: this.inputText, placeholder: '说点什么...' }) + .layoutWeight(1) + .onChange((value: string) => { + this.inputText = value + }) + .onSubmit(() => { // 回车发送 + this.sendMessage() + }) + + Button('发送', { type: ButtonType.Capsule }) + .backgroundColor('#007AFF') + .onClick(() => { + this.sendMessage() + }) + } + .padding(10) + .backgroundColor('#F5F5F5') + } + .width('100%') + .height('100%') + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ListChatRoom_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListDataSource.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..07e4de1fe56f77093f568dca498e66235f0e6191 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListDataSource.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. + */ + +export class ListDataSource implements IDataSource { + private list: number[] = []; + private listeners: DataChangeListener[] = []; + + constructor(list: number[]) { + this.list = list; + } + + totalCount(): number { + return this.list.length; + } + + getData(index: number): number { + return this.list[index]; + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener); + } + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + // 通知控制器数据删除 + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }); + } + + // 在指定索引位置删除一个元素 + public deleteItem(index: number): void { + this.list.splice(index, 1); + this.notifyDataDelete(index); + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListIteration.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListIteration.ets new file mode 100644 index 0000000000000000000000000000000000000000..9d307842428c8c410f7804c7769f4bcac1c02b2e --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListIteration.ets @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start use_foreach_to_replace_similar_list_items] +import { util } from '@kit.ArkTS'; +// [StartExclude import_component_card] +import { ComponentCard } from '../../common/Card'; +// [EndExclude import_component_card] + +class Contact { + public key: string = util.generateRandomUUID(true); + public name: ResourceStr; + public icon: Resource; + + constructor(name: ResourceStr, icon: Resource) { + this.name = name; + this.icon = icon; + } +} + +@Entry +@Component +export struct ListIteration { + private contacts: Array = [ + new Contact($r('app.string.peopleOne'), $r('sys.media.clone_app_badge_1')), + new Contact($r('app.string.peopleTwo'), $r('sys.media.clone_app_badge_2')) + ]; + + build() { + // [StartExclude use_the_nav_destination] + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ListIteration_titleExample') }) { + // [EndExclude use_the_nav_destination] + List() { + ForEach(this.contacts, (item: Contact) => { + ListItem() { + Row() { + Image(item.icon) + .width(40) + .height(40) + .margin(10) + Text(item.name).fontSize(20) + } + .width('100%') + .justifyContent(FlexAlign.Start) + } + }, (item: Contact) => JSON.stringify(item)) + } + .width('100%') + } + } + // [End use_foreach_to_replace_similar_list_items] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ListIteration_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListLayout.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListLayout.ets new file mode 100644 index 0000000000000000000000000000000000000000..742098ded73f871f74bbee3487d4c3d87cb93fdf --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ListLayout.ets @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ListLayout { + @State egLanes: LengthConstrain = { minLength: 200, maxLength: 300 }; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ListLayout_titleMainAxis') }) { + // [Start build_a_horizontal_scrolling_list] + List({ space: 8 }) { + // [StartExclude build_a_horizontal_scrolling_list] + ListItem() { + Text('ListItem one') + } + + ListItem() { + Text('ListItem two') + } + // [EndExclude build_a_horizontal_scrolling_list] + } + .listDirection(Axis.Horizontal) + // [End build_a_horizontal_scrolling_list] + .height(30) + } + + ComponentCard({ title: $r('app.string.ListLayout_titleCrossAxisLanes') }) { + // [Start build_list_by_size] + List({ space: 8 }) { + ListItem() { + // [StartExclude build_list_by_size] + Text('ListItem one') + } + + ListItem() { + Text('ListItem two') + } + + ListItem() { + Text('ListItem tree') + } + // [EndExclude build_list_by_size] + } + // 此处lanes设置主轴方向 + .lanes(this.egLanes) + // [End build_list_by_size] + } + + ComponentCard({ title: $r('app.string.ListLayout_titleCrossAxisAlignment') }) { + // [Start build_list_with_align_horizontally_in_the_center] + List({ space: 8 }) { + // [StartExclude build_list_with_align_horizontally_in_the_center] + ListItem() { + Text('ListItem one') + } + + ListItem() { + Text('ListItem two') + } + + ListItem() { + Text('ListItem tree') + } + // [EndExclude build_list_with_align_horizontally_in_the_center] + } + // 此处alignListItem设置水平方向对齐 + .alignListItem(ListItemAlign.Center) + // [End build_list_with_align_horizontally_in_the_center] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ListLayout_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/LongList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/LongList.ets new file mode 100644 index 0000000000000000000000000000000000000000..6c5fd86c5de5d90eab101c5a74fe607903e1b9ee --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/LongList.ets @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; +import { ListDataSource } from './ListDataSource'; + +@Entry +@Component +export struct LongList { + private arr: ListDataSource = new ListDataSource([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.LongList_title') }) { + List({ space: 20, initialIndex: 0 }) { + LazyForEach(this.arr, (item: number) => { + ListItem() { + Text('' + item) + .width('100%').height(100).fontSize(16) + .textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF) + } + }, (item: string) => item) + } + .listDirection(Axis.Vertical) // 排列方向 + .scrollBar(BarState.Off) + .friction(0.6) + .divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线 + .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring + .onScrollIndex((firstIndex: number, lastIndex: number, centerIndex: number) => { + console.info('first' + firstIndex); + console.info('last' + lastIndex); + console.info('center' + centerIndex); + }) + .onScrollVisibleContentChange((start: VisibleListContentInfo, end: VisibleListContentInfo) => { + console.log(' start index: ' + start.index + + ' start item group area: ' + start.itemGroupArea + + ' start index in group: ' + start.itemIndexInGroup); + console.log(' end index: ' + end.index + + ' end item group area: ' + end.itemGroupArea + + ' end index in group: ' + end.itemIndexInGroup); + }) + .onDidScroll((scrollOffset: number, scrollState: ScrollState) => { + console.info(`onScroll scrollState = ScrollState` + scrollState + `, scrollOffset = ` + scrollOffset); + }) + .width('90%') + } + } + .backgroundColor(0xDCDCDC) + .width('100%') + .height('100%') + } + .title($r('app.string.LongList_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ResponsiveScrollPositionList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ResponsiveScrollPositionList.ets new file mode 100644 index 0000000000000000000000000000000000000000..06c536cdbd230d39acab2ff89c16e21b37debfbb --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/ResponsiveScrollPositionList.ets @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { util } from '@kit.ArkTS'; +import { ComponentCard } from '../../common/Card'; + +// [Start respond_to_scroll_position] +const alphabets = ['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; + +// [StartExclude respond_to_scroll_position] +class Contact { + public key: string = util.generateRandomUUID(true); + public name: string | Resource; + public icon: Resource; + + constructor(name: string | Resource, icon: Resource) { + this.name = name; + this.icon = icon; + } +} + +class ContactsGroup { + public title: string = ''; + public contacts: Array | null = null; + public key: string = ''; +} + +export let contactsGroups: object[] = [ + { + title: 'A', + contacts: [ + new Contact($r('app.string.contacts_A_one'), $r('sys.media.clone_app_badge_1')), + new Contact($r('app.string.contacts_A_two'), $r('sys.media.clone_app_badge_2')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'B', + contacts: [ + new Contact($r('app.string.contacts_B_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_B_two'), $r('sys.media.clone_app_badge_4')), + new Contact($r('app.string.contacts_B_three'), $r('sys.media.clone_app_badge_5')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'D', + contacts: [ + new Contact($r('app.string.contacts_D_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_D_two'), $r('sys.media.clone_app_badge_4')), + new Contact($r('app.string.contacts_D_three'), $r('sys.media.clone_app_badge_5')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'F', + contacts: [ + new Contact($r('app.string.contacts_F_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_F_two'), $r('sys.media.clone_app_badge_4')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'G', + contacts: [ + new Contact($r('app.string.contacts_G_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_G_two'), $r('sys.media.clone_app_badge_4')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'H', + contacts: [ + new Contact($r('app.string.contacts_H_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_H_two'), $r('sys.media.clone_app_badge_4')), + new Contact($r('app.string.contacts_H_three'), $r('sys.media.clone_app_badge_5')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'X', + contacts: [ + new Contact($r('app.string.contacts_X_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_X_two'), $r('sys.media.clone_app_badge_4')), + new Contact($r('app.string.contacts_X_three'), $r('sys.media.clone_app_badge_5')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup +]; +// [EndExclude respond_to_scroll_position] + +@Entry +@Component +export struct ResponsiveScrollPositionList { + @State selectedIndex: number = 0; + private listScroller: Scroller = new Scroller(); + private currentGroupTitle: string = ''; // 用于跟踪当前显示的分组标题 + + // [StartExclude respond_to_scroll_position] + @Builder + itemHead(text: string) { + // 列表分组的头部组件,对应联系人分组A、B等位置的组件 + Text(text) + .fontSize(20) + .backgroundColor('#fff1f3f5') + .width('100%') + .padding(5) + } + // [EndExclude respond_to_scroll_position] + + build() { + // [StartExclude respond_to_scroll_position] + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ResponsiveScrollPositionList_titleExample') }) { + // [EndExclude use_stack] + Stack({ alignContent: Alignment.End }) { + // 此为响应滚动位置示例List容器 + List({ scroller: this.listScroller }) { + // [StartExclude use_foreach] + ForEach(contactsGroups, (itemGroup: ContactsGroup) => { + ListItemGroup({ header: this.itemHead(itemGroup.title) }) { + // 循环渲染ListItem + if (itemGroup.contacts) { + ForEach(itemGroup.contacts, (item: Contact) => { + ListItem() { + Row() { + Image(item.icon).width(40).height(40).margin(10) + Text(item.name).fontSize(20) + }.width('100%').justifyContent(FlexAlign.Start) + // [EndExclude respond_to_scroll_position] + } + // [StartExclude respond_to_scroll_position] + }, (item: Contact) => JSON.stringify(item)) + } + } + }, (itemGroup: ContactsGroup) => JSON.stringify(itemGroup)) + } + // [EndExclude respond_to_scroll_position] + .onScrollIndex((firstIndex: number) => { + // [StartExclude respond_to_scroll_position] + // 根据列表滚动到的索引值,重新计算对应联系人索引栏的位置this.selectedIndex + let group = contactsGroups[firstIndex] as ContactsGroup; + this.currentGroupTitle = group.title; + this.selectedIndex = alphabets.indexOf(this.currentGroupTitle); + // [EndExclude respond_to_scroll_position] + }) + + // 字母表索引组件 + AlphabetIndexer({ arrayValue: alphabets, selected: 0 }) + .selected(this.selectedIndex) + // [End respond_to_scroll_position] + }.height('90%') + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ResponsiveScrollPositionList_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/StickyHeaderList.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/StickyHeaderList.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c2194578b28197f2c27a07dedb2a094ceb44908 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/StickyHeaderList.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 { ComponentCard } from '../../common/Card'; +// [Start Add_sticky_titles] +import { util } from '@kit.ArkTS'; + +class Contact { + public key: string = util.generateRandomUUID(true); + public name: string | Resource; + public icon: Resource; + + constructor(name: string | Resource, icon: Resource) { + this.name = name; + this.icon = icon; + } +} + +class ContactsGroup { + public title: string = ''; + public contacts: Array | null = null; + public key: string = ''; +} + +export let contactsGroups: object[] = [ + { + title: 'A', + contacts: [ + new Contact($r('app.string.contacts_A_one'), $r('sys.media.clone_app_badge_1')), + new Contact($r('app.string.contacts_A_two'), $r('sys.media.clone_app_badge_2')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup, + { + title: 'B', + contacts: [ + new Contact($r('app.string.contacts_B_one'), $r('sys.media.clone_app_badge_3')), + new Contact($r('app.string.contacts_B_two'), $r('sys.media.clone_app_badge_4')), + new Contact($r('app.string.contacts_B_three'), $r('sys.media.clone_app_badge_5')) + ], + key: util.generateRandomUUID(true) + } as ContactsGroup +]; + +@Entry +@Component +export struct StickyHeaderList { + // 定义分组联系人数据集合contactsGroups数组 + @Builder + itemHead(text: string) { + // 列表分组的头部组件,对应联系人分组A、B等位置的组件 + Text(text) + .fontSize(20) + .backgroundColor('#fff1f3f5') + .width('100%') + .padding(5) + } + + build() { + // [StartExclude add_sticky_titles] + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.StickyHeaderList_titleExample') }) { + // [EndExclude add_sticky_titles] + List() { + // 循环渲染ListItemGroup,contactsGroups为多个分组联系人contacts和标题title的数据集合 + ForEach(contactsGroups, (itemGroup: ContactsGroup) => { + ListItemGroup({ header: this.itemHead(itemGroup.title) }) { + // 循环渲染ListItem + if (itemGroup.contacts) { + ForEach(itemGroup.contacts, (item: Contact) => { + ListItem() { + // [StartExclude add_sticky_titles] + Row() { + Image(item.icon).width(40).height(40).margin(10) + Text(item.name).fontSize(20) + }.width('100%').justifyContent(FlexAlign.Start) + // [EndExclude add_sticky_titles] + } + }, (item: Contact) => JSON.stringify(item)) + } + } + }, (itemGroup: ContactsGroup) => JSON.stringify(itemGroup)) + } + // [StartExclude add_sticky_titles] + .height(230) + // [EndExclude add_sticky_titles] + .sticky(StickyStyle.Header) // 设置吸顶,实现粘性标题效果 + } + // [End add_sticky_titles] + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.StickyHeaderList_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/SwipeableListItem.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/SwipeableListItem.ets new file mode 100644 index 0000000000000000000000000000000000000000..7f6454c43ba480fbeadaa8a56232f3f3edc202b6 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/SwipeableListItem.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. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwipeListItem { + private index: number = 0; + @State arr: number[] = [0, 1, 2, 3]; + + // [Start build_the_tail_slide_out_component] + @Builder + itemEnd(index: number) { + // 构建尾端滑出组件 + Button({ type: ButtonType.Circle }) { + Image($r('sys.media.ohos_ic_bottomsheet_close')) + .width(40) + .height(40) + } + // [StartExclude build_the_tail_slide_out_component] + .backgroundColor('#FFE1E2E3') + // [EndExclude build_the_tail_slide_out_component] + .onClick(() => { + // this.messages为列表数据源,可根据实际场景构造。点击后从数据源删除指定数据项。 + this.arr.splice(index, 1); + }) + } + // [End build_the_tail_slide_out_component] + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwipeListItem_titleExample') }) { + List({ space: 12 }) { + ForEach(this.arr, (item: number) => { + // [Start bind_the_swipeAction_property_to_left_swipe_list_item] + ListItem() { + // [StartExclude bind_the_swipeAction_property_to_left_swipe_list_item] + Text('Message ' + item) + .width('100%') + .height(50) + .fontSize(16) + .textAlign(TextAlign.Center) + .borderRadius(10) + .backgroundColor('#FFF1F3F5') + // [EndExclude bind_the_swipeAction_property_to_left_swipe_list_item] + }.swipeAction({ + end: { + // index为该ListItem在List中的索引值。 + builder: () => { + this.index = this.arr.indexOf(item); + this.itemEnd(this.index); + }, + } + // [End bind_the_swipeAction_property_to_left_swipe_list_item] + }) + }, (item: number) => item.toString()) + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwipeListItem_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/TaggedListItems.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/TaggedListItems.ets new file mode 100644 index 0000000000000000000000000000000000000000..bee859a3324828758ef49b72468a59988752ed16 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/list/TaggedListItems.ets @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct TaggedListItems { + @State arr: number[] = [0, 1, 2, 3]; + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.TaggedListItems_titleExample') }) { + List() { + ForEach(this.arr, (item: number) => { + // [Start add_tags_to_list_items] + ListItem() { + // Badge组件实现消息右上角添加标记功能 + Badge({ + count: 1, + position: BadgePosition.RightTop, + style: { badgeSize: 16, badgeColor: '#FA2A2D' } + }) { + // [StartExclude add_tags_to_list_items] + Text('消息' + item) + .width('95%') + .height(50) + .fontSize(16) + .textAlign(TextAlign.Center) + .borderRadius(10) + .backgroundColor('#FFF1F3F5') + // [EndExclude add_tags_to_list_items] + } + // [End add_tags_to_list_items] + }.margin({ top: 12 }) + }, (item: number) => item.toString()) + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.TaggedListItems_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAndTabsLinkage.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAndTabsLinkage.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b6320ccd976e470890217dae13cd3d61caa0ce2 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAndTabsLinkage.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 { ComponentCard } from "../../common/Card"; + +// xxx.ets +class MyDataSource implements IDataSource { + private list: number[] = []; + + constructor(list: number[]) { + this.list = list; + } + + totalCount(): number { + return this.list.length; + } + + getData(index: number): number { + return this.list[index]; + } + + registerDataChangeListener(listener: DataChangeListener): void { + } + + unregisterDataChangeListener() { + } +} + +@Entry +@Component +export struct SwiperAndTabsLinkage { + @State fontColor: string = '#182431'; + @State selectedFontColor: string = '#007DFF'; + @State currentIndex: number = 0; + private list: number[] = []; + private tabsController: TabsController = new TabsController(); + private swiperController: SwiperController = new SwiperController(); + private swiperData: MyDataSource = new MyDataSource([]); + + aboutToAppear(): void { + for (let i = 0; i <= 9; i++) { + this.list.push(i); + } + this.swiperData = new MyDataSource(this.list); + } + + @Builder tabBuilder(index: number, name: string) { + Column() { + Text(name) + .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) + .fontSize(16) + .fontWeight(this.currentIndex === index ? 500 : 400) + .lineHeight(22) + .margin({ top: 17, bottom: 7 }) + Divider() + .strokeWidth(2) + .color('#007DFF') + .opacity(this.currentIndex === index ? 1 : 0) + }.width('20%') + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperAndTabsLinkage_title') }) { + Column() { + Tabs({ barPosition: BarPosition.Start, controller: this.tabsController }) { + ForEach(this.list, (index: number) =>{ + TabContent().tabBar(this.tabBuilder(index, '页签 ' + this.list[index])) + }) + } + .onTabBarClick((index: number) => { + this.currentIndex = index; + this.swiperController.changeIndex(index, true); + }) + .barMode(BarMode.Scrollable) + .backgroundColor('#F1F3F5') + .height(56) + .width('100%') + + Swiper(this.swiperController) { + LazyForEach(this.swiperData, (item: string) => { + Text(item.toString()) + .onAppear(()=>{ + console.info('onAppear ' + item.toString()); + }) + .onDisAppear(()=>{ + console.info('onDisAppear ' + item.toString()); + }) + .width('100%') + .height('40%') + .backgroundColor(0xAFEEEE) + .textAlign(TextAlign.Center) + .fontSize(30) + }, (item: string) => item) + } + .loop(false) + .onSelected((index: number) => { + console.info("onSelected:" + index); + this.currentIndex = index; + this.tabsController.changeIndex(index); + }) + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperAndTabsLinkage_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAutoPlay.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAutoPlay.ets new file mode 100644 index 0000000000000000000000000000000000000000..9900409f00f30ae6fb66be820cfe3e89faf4eb21 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAutoPlay.ets @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwiperAutoPlay { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperAutoPlay_title') }) { + // [Start autoplay_loop_true] + Swiper() { + // [StartExclude autoplay_loop_true] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude autoplay_loop_true] + } + // [StartExclude autoplay_loop_true] + .height(200) + // [EndExclude autoplay_loop_true] + .loop(true) + .autoPlay(true) + .interval(1000) + // [End autoplay_loop_true] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperAutoPlay_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperCustomAnimation.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperCustomAnimation.ets new file mode 100644 index 0000000000000000000000000000000000000000..43bab941cd801286eb7f8f6afd7c01304e384702 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperCustomAnimation.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 { ComponentCard } from '../../common/Card'; + +// [Start customize_transition_animations] +@Entry +@Component +export struct SwiperCustomAnimation { + private DISPLAY_COUNT: number = 2; + private MIN_SCALE: number = 0.75; + @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange]; + @State opacityList: number[] = []; + @State scaleList: number[] = []; + @State translateList: number[] = []; + @State zIndexList: number[] = []; + + aboutToAppear(): void { + for (let i = 0; i < this.backgroundColors.length; i++) { + this.opacityList.push(1.0); + this.scaleList.push(1.0); + this.translateList.push(0.0); + this.zIndexList.push(0); + } + } + + build() { + // [StartExclude customize_transition_animations] + NavDestination() { + // [EndExclude customize_transition_animations] + Column({ space: 12 }) { + // [StartExclude customize_transition_animations] + ComponentCard({ title: $r('app.string.SwiperCustomAnimation_titleExample') }) { + // [EndExclude customize_transition_animations] + Swiper() { + ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => { + Text(index.toString()) + .width('100%') + .height('100%') + .fontSize(50) + .textAlign(TextAlign.Center) + .backgroundColor(backgroundColor) + .opacity(this.opacityList[index]) + .scale({ x: this.scaleList[index], y: this.scaleList[index] }) + .translate({ x: this.translateList[index] }) + .zIndex(this.zIndexList[index]) + }) + } + .height(200) + .indicator(false) + .displayCount(this.DISPLAY_COUNT, true) + .customContentTransition({ + timeout: 1000, + transition: (proxy: SwiperContentTransitionProxy) => { + if (proxy.position <= proxy.index % this.DISPLAY_COUNT || + proxy.position >= this.DISPLAY_COUNT + proxy.index % this.DISPLAY_COUNT) { + // 同组页面完全滑出视窗外时,重置属性值 + this.opacityList[proxy.index] = 1.0; + this.scaleList[proxy.index] = 1.0; + this.translateList[proxy.index] = 0.0; + this.zIndexList[proxy.index] = 0; + } else { + // 同组页面未滑出视窗外时,对同组中左右两个页面,逐帧根据position修改属性值 + if (proxy.index % this.DISPLAY_COUNT === 0) { + this.opacityList[proxy.index] = 1 - proxy.position / this.DISPLAY_COUNT; + this.scaleList[proxy.index] = + this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - proxy.position / this.DISPLAY_COUNT); + this.translateList[proxy.index] = -proxy.position * proxy.mainAxisLength + + (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0; + } else { + this.opacityList[proxy.index] = 1 - (proxy.position - 1) / this.DISPLAY_COUNT; + this.scaleList[proxy.index] = + this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - (proxy.position - 1) / this.DISPLAY_COUNT); + this.translateList[proxy.index] = -(proxy.position - 1) * proxy.mainAxisLength - + (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0; + } + this.zIndexList[proxy.index] = -1; + } + } + }) + } + } + .width('100%') + // [End customize_transition_animations] + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperCustomAnimation_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperDirection.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperDirection.ets new file mode 100644 index 0000000000000000000000000000000000000000..e8c8e2d9cdb23d69cce3cb5a9b826e56110c1bd3 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperDirection.ets @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwiperDirection { + private swiperHorizontalController: SwiperController = new SwiperController(); + private swiperVerticalController: SwiperController = new SwiperController(); + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperPageSwitchMethod_titleHorizontal') }) { + Column({ space: 8 }) { + // [Start rotate_horizontally] + Swiper(this.swiperHorizontalController) { + // [StartExclude rotate_horizontally] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude rotate_horizontally] + } + // [StartExclude rotate_horizontally] + .height(200) + // [EndExclude rotate_horizontally] + .indicator(true) + .vertical(false) + // [End rotate_horizontally] + + Row({ space: 12 }) { + Button('showNext') + .onClick(() => { + this.swiperHorizontalController.showNext(); // 通过controller切换到后一页 + }) + Button('showPrevious') + .onClick(() => { + this.swiperHorizontalController.showPrevious(); // 通过controller切换到前一页 + }) + }.margin(5) + } + } + + ComponentCard({ title: $r('app.string.SwiperPageSwitchMethod_titleVertical') }) { + Column({ space: 8 }) { + // [Start rotate_vertically] + Swiper(this.swiperVerticalController) { + // [StartExclude rotate_vertically] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude rotate_vertically] + } + // [StartExclude rotate_vertically] + .height(200) + // [EndExclude rotate_vertically] + .indicator(true) + .vertical(true) + // [End rotate_vertically] + + Row({ space: 12 }) { + Button('showNext') + .onClick(() => { + this.swiperVerticalController.showNext(); // 通过controller切换到后一页 + }) + Button('showPrevious') + .onClick(() => { + this.swiperVerticalController.showPrevious(); // 通过controller切换到前一页 + }) + }.margin(5) + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperDirection_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIgnoreComponentSize.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIgnoreComponentSize.ets new file mode 100644 index 0000000000000000000000000000000000000000..420343eb510941dde4c0e9565b2d06c0df0124ef --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIgnoreComponentSize.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 { LengthMetrics } from '@kit.ArkUI'; +import { ComponentCard } from '../../common/Card'; + + +class MyDataSource implements IDataSource { + private list: number[] = []; + + constructor(list: number[]) { + this.list = list; + } + + totalCount(): number { + return this.list.length; + } + + getData(index: number): number { + return this.list[index]; + } + + registerDataChangeListener(listener: DataChangeListener): void { + } + + unregisterDataChangeListener() { + } +} + +@Entry +@Component +export struct SwiperIgnoreComponentSize { + + @State space: LengthMetrics = LengthMetrics.vp(0); + @State spacePool: LengthMetrics[] = [LengthMetrics.vp(0), LengthMetrics.px(3), LengthMetrics.vp(10)]; + @State spaceIndex: number = 0; + + @State ignoreSize: boolean = false; + @State ignoreSizePool: boolean[] = [false, true]; + @State ignoreSizeIndex: number = 0; + + private swiperController1: SwiperController = new SwiperController(); + private data1: MyDataSource = new MyDataSource([]); + + aboutToAppear(): void { + let list1: number[] = []; + for (let i = 1; i <= 10; i++) { + list1.push(i); + } + this.data1 = new MyDataSource(list1); + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperIgnoreComponentSize_title') }) { + Scroll() { + Column({ space: 20 }) { + Swiper(this.swiperController1) { + LazyForEach(this.data1, (item: string) => { + Text(item.toString()) + .width('90%') + .height(120) + .backgroundColor(0xAFEEEE) + .textAlign(TextAlign.Center) + .fontSize(30) + }, (item: string) => item) + } + .indicator(new DotIndicator() + .space(this.space) + .bottom(LengthMetrics.vp(0), this.ignoreSize) + .itemWidth(15) + .itemHeight(15) + .selectedItemWidth(15) + .selectedItemHeight(15) + .color(Color.Gray) + .selectedColor(Color.Blue)) + .displayArrow({ + showBackground: true, + isSidebarMiddle: true, + backgroundSize: 24, + backgroundColor: Color.White, + arrowSize: 18, + arrowColor: Color.Blue + }, false) + + Column({ space: 4 }) { + Button('spaceIndex:' + this.spaceIndex).onClick(() => { + this.spaceIndex = (this.spaceIndex + 1) % this.spacePool.length; + this.space = this.spacePool[this.spaceIndex]; + }).margin(10) + + Button('ignoreSizeIndex:' + this.ignoreSizeIndex).onClick(() => { + this.ignoreSizeIndex = (this.ignoreSizeIndex + 1) % this.ignoreSizePool.length; + this.ignoreSize = this.ignoreSizePool[this.ignoreSizeIndex]; + }).margin(10) + }.margin(2) + }.width('100%') + } + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperIgnoreComponentSize_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIndicatorStyle.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIndicatorStyle.ets new file mode 100644 index 0000000000000000000000000000000000000000..b38d27d167c886bc92ed0d5dc59418bb7604991b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIndicatorStyle.ets @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwiperIndicatorStyle { + build() { + NavDestination() { + Column({ space: 12 }) { + + ComponentCard({ title: $r('app.string.SwiperIndicatorStyle_titleDefault') }) { + // [Start default_navigation_point_style] + Swiper() { + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + // [End default_navigation_point_style] + .height(100) + } + + ComponentCard({ title: $r('app.string.SwiperIndicatorStyle_titleCustom') }) { + // [Start customize_navigation_point_styles] + Swiper() { + // [StartExclude customize_navigation_point_styles] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude customize_navigation_point_styles] + } + .height(100) + .indicator( + Indicator.dot() + .left(0) + .itemWidth(15) + .itemHeight(15) + .selectedItemWidth(30) + .selectedItemHeight(15) + .color(Color.Red) + .selectedColor(Color.Blue) + ) + } + // [End customize_navigation_point_styles] + + ComponentCard({ title: $r('app.string.SwiperIndicatorStyle_titleDefaultArrows') }) { + // [Start default_arrow_style] + Swiper() { + // [StartExclude default_arrow_style] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude default_arrow_style] + } + // [StartExclude default_arrow_style] + .height(100) + // [EndExclude default_arrow_style] + .displayArrow(true, false) + // [End default_arrow_style] + } + + ComponentCard({ title: $r('app.string.SwiperIndicatorStyle_titleCustomArrows') }) { + // [Start customize_the_arrow_style] + Swiper() { + // [StartExclude customize_the_arrow_style] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude customize_the_arrow_style] + } + // [StartExclude customize_the_arrow_style] + .height(100) + // [EndExclude customize_the_arrow_style] + .displayArrow({ + showBackground: true, + isSidebarMiddle: true, + backgroundSize: 24, + backgroundColor: Color.White, + arrowSize: 18, + arrowColor: Color.Blue + }, false) + // [End customize_the_arrow_style] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperIndicatorStyle_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperLoop.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperLoop.ets new file mode 100644 index 0000000000000000000000000000000000000000..10c4945f09b7966c2b10ed4abfed524fdef03f9c --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperLoop.ets @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwiperLoop { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperLoop_titleTrue') }) { + // [Start loop_with_true] + Swiper() { + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + // [StartExclude loop_with_true] + .height(200) + // [EndExclude loop_with_true] + .loop(true) + // [End loop_with_true] + } + + ComponentCard({ title: $r('app.string.SwiperLoop_titleFalse') }) { + // [Start loop_with_false] + Swiper() { + // [StartExclude loop_with_false] + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + // [EndExclude loop_with_false] + } + // [StartExclude loop_with_false] + .height(200) + // [EndExclude loop_with_false] + .loop(false) + // [End loop_with_false] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperLoop_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperMultiPage.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperMultiPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..e534dd9f1002254fcb9f1ea0edc4455ac892f2c9 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperMultiPage.ets @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwiperMultiPage { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperMultiPage_titleExample') }) { + // [Start each_page_displays_multiple_subpages] + Swiper() { + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + Text('3') + .width('90%') + .height('100%') + .backgroundColor(Color.Yellow) + .textAlign(TextAlign.Center) + .fontSize(30) + } + // [StartExclude each_page_displays_multiple_subpages] + .height(200) + // [EndExclude each_page_displays_multiple_subpages] + .indicator(true) + .displayCount(2) + } + // [End each_page_displays_multiple_subpages] + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperMultiPage_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperPageSwitchMethod.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperPageSwitchMethod.ets new file mode 100644 index 0000000000000000000000000000000000000000..64ae9a299941977d3e3bdf1ffbff1f994838cfde --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperPageSwitchMethod.ets @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +// [Start switch_pages] +@Entry +@Component +export struct SwiperPageSwitchMethod { + private swiperController: SwiperController = new SwiperController(); + + build() { + // [StartExclude switch_pages] + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwiperPageSwitchMethod_title') }) { + // [EndExclude switch_pages] + Column({ space: 8 }) { + Swiper(this.swiperController) { + Text('0') + .width('90%') + .height('100%') + .backgroundColor(Color.Gray) + .textAlign(TextAlign.Center) + .fontSize(30) + Text('1') + .width('90%') + .height('100%') + .backgroundColor(Color.Green) + .textAlign(TextAlign.Center) + .fontSize(30) + Text('2') + .width('90%') + .height('100%') + .backgroundColor(Color.Pink) + .textAlign(TextAlign.Center) + .fontSize(30) + } + // [StartExclude switch_pages] + .height(200) + // [EndExclude switch_pages] + .indicator(true) + + Row({ space: 12 }) { + Button('showNext') + .onClick(() => { + this.swiperController.showNext(); // 通过controller切换到后一页 + }) + Button('showPrevious') + .onClick(() => { + this.swiperController.showPrevious(); // 通过controller切换到前一页 + }) + }.margin(5) + } + } + } + // [End switch_pages] + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwiperPageSwitchMethod_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..37aa2ea07443fc9bb7f149c03d90906f217a4379 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { SwiperAutoPlay } from './SwiperAutoPlay'; +import { SwiperCustomAnimation } from './SwiperCustomAnimation'; +import { SwiperDirection } from './SwiperDirection'; +import { SwiperIndicatorStyle } from './SwiperIndicatorStyle'; +import { SwiperLoop } from './SwiperLoop'; +import { SwiperMultiPage } from './SwiperMultiPage'; +import { SwiperPageSwitchMethod } from './SwiperPageSwitchMethod'; +import { SwiperAndTabsLinkage } from './SwiperAndTabsLinkage'; +import resource from '../../common/resource'; + +export const SWIPER_ROUTE_PREFIX: string = 'swiper'; + +const routes: Route[] = [ + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperLoop`, + title: resource.resourceToString($r('app.string.SwiperLoop_title')), + description: $r('app.string.SwiperLoop_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperAutoPlay`, + title: resource.resourceToString($r('app.string.SwiperAutoPlay_title')), + description: $r('app.string.SwiperAutoPlay_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperIndicatorStyle`, + title: resource.resourceToString($r('app.string.SwiperIndicatorStyle_title')), + description: $r('app.string.SwiperIndicatorStyle_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperPageSwitchMethod`, + title: resource.resourceToString($r('app.string.SwiperPageSwitchMethod_title')), + description: $r('app.string.SwiperPageSwitchMethod_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperDirection`, + title: resource.resourceToString($r('app.string.SwiperDirection_title')), + description: $r('app.string.SwiperDirection_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperMultiPage`, + title: resource.resourceToString($r('app.string.SwiperMultiPage_title')), + description: $r('app.string.SwiperMultiPage_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperCustomAnimation`, + title: resource.resourceToString($r('app.string.SwiperCustomAnimation_title')), + description: $r('app.string.SwiperCustomAnimation_description') + }, + { + name: `${SWIPER_ROUTE_PREFIX}/SwiperAndTabsLinkage`, + title: resource.resourceToString($r('app.string.SwiperAndTabsLinkage_title')), + description: $r('app.string.SwiperAndTabsLinkage_description') + } +]; + +@Builder +export function swiperDestination(name: string) { + if (name === SWIPER_ROUTE_PREFIX) { + SwiperExample(); + } else if (name === routes[0].name) { + SwiperLoop(); + } else if (name === routes[1].name) { + SwiperAutoPlay(); + } else if (name === routes[2].name) { + SwiperIndicatorStyle(); + } else if (name === routes[3].name) { + SwiperPageSwitchMethod(); + } else if (name === routes[4].name) { + SwiperDirection(); + } else if (name === routes[5].name) { + SwiperMultiPage(); + } else if (name === routes[6].name) { + SwiperCustomAnimation(); + } else if (name === routes[7].name) { + SwiperAndTabsLinkage(); + } +} + +@Entry +@Component +struct SwiperExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('Swiper', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/AgeFriendlyTabs.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/AgeFriendlyTabs.ets new file mode 100644 index 0000000000000000000000000000000000000000..74d7a869758a332660676805b3cd1b699fd5035f --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/AgeFriendlyTabs.ets @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 age_friendly_tab] +import { abilityManager, Configuration } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { promptAction, uiAppearance } from '@kit.ArkUI'; + +@Entry +@Component +export struct AgeFriendlyTabs { + @State fontColor: string = '#182431'; + @State selectedFontColor: string = '#007DFF'; + @State currentIndex: number = 0; + @State currentFontSizeScale: string = ''; + @State showBuilderTab: boolean = false; + @State fontSize: number = 15; + private darkModeKey: string[] = Object.keys(uiAppearance.DarkMode).filter( + key => typeof uiAppearance.DarkMode[key] === 'number'); + + async setFontScale(scale: number): Promise { + let configInit: Configuration = { + fontSizeScale: scale, + }; + abilityManager.updateConfiguration(configInit, (err: BusinessError) => { + if (err) { + console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`); + promptAction.showToast({ message: `scale:${scale}, err:${JSON.stringify(err)}` }); + } else { + this.currentFontSizeScale = String(scale); + if (scale > 1) { + this.fontSize = 8; + } else { + this.fontSize = 15; + } + console.log('updateConfiguration success.'); + promptAction.showToast({ message: `scale:${scale}, updateConfiguration success.` }); + } + }); + } + + darkMode(isDarkMode: boolean): void { + let mode: uiAppearance.DarkMode = uiAppearance.DarkMode.ALWAYS_LIGHT; + if (isDarkMode) { + mode = uiAppearance.DarkMode.ALWAYS_DARK; + } + if (mode == uiAppearance.getDarkMode()) { + console.info(`TitleDarkMode Set ${this.darkModeKey[mode]} successfully.`); + return; + } + try { + uiAppearance.setDarkMode(mode).then(() => { + console.info(`TitleDarkMode Set ${this.darkModeKey[mode]} successfully.`); + }).catch((error: Error) => { + console.error(`TitleDarkMode Set ${this.darkModeKey[mode]} failed, ${error.message}`); + }); + } catch (error) { + let message = (error as BusinessError).message; + console.error(`TitleDarkMode Set dark-mode failed, ${message}`); + } + } + + build() { + // [StartExclude age_friendly_tab] + NavDestination() { + // [EndExclude age_friendly_tab] + Column() { + Column() { + Row() { + Text(`current fontSizeScale:${this.currentFontSizeScale}`) + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + } + + Row() { + Button('1.75') + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + .width('40%') + .onClick(async () => { + await this.setFontScale(1.75); + }) + Button('2') + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + .width('40%') + .onClick(async () => { + await this.setFontScale(2); + }) + }.margin({ top: 25 }) + + Row() { + Button('3.2') + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + .width('40%') + .onClick(async () => { + await this.setFontScale(3.2); + }) + Button('1') + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + .width('40%') + .onClick(async () => { + await this.setFontScale(1); + }) + } + + Row() { + Button('深色模式') + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + .width('40%') + .onClick(async () => { + this.darkMode(true); + }) + Button('浅色模式') + .margin({ top: 5, bottom: 5 }) + .fontSize(this.fontSize) + .width('40%') + .onClick(async () => { + this.darkMode(false); + }) + } + }.alignItems(HorizontalAlign.Start) + + Column() { + Tabs({ barPosition: BarPosition.End }) { + TabContent() { + Column() + .width('100%') + .height('100%') + .backgroundColor(Color.Pink) + }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'OverLength')) + + TabContent() { + Column() + .width('100%') + .height('100%') + .backgroundColor(Color.Yellow) + }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'SixLine')) + + TabContent() { + Column() + .width('100%') + .height('100%') + .backgroundColor(Color.Blue) + }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Blue')) + + TabContent() { + Column() + .width('100%') + .height('100%') + .backgroundColor(Color.Green) + }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Green')) + } + .vertical(false) + .scrollable(true) + .barMode(BarMode.Fixed) + .onChange((index: number) => { + console.info(index.toString()); + }) + .width('100%') + .backgroundColor(0xF1F3F5) + }.width('80%').height(200) + .margin({ top: 200 }) + }.width('100%') + } + // [End age_friendly_tab] + .backgroundColor('#f1f2f3') + .title($r('app.string.AgeFriendlyTabs_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/BottomTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/BottomTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..9a3a5b4215532191af05cdcf796c450451076814 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/BottomTabBar.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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct BottomTabBar { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.BottomTabBar_titleExample') }) { + // [Start bottom_navigation] + Tabs({ barPosition: BarPosition.End }) { + // [StartExclude bottom_navigation] + TabContent() { + Text($r('app.string.homepage_content')) + .fontSize(30) + + } + .backgroundColor(Color.Blue) + .tabBar($r('app.string.homepage')) + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar($r('app.string.recommend')) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar($r('app.string.discover')) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar($r('app.string.mine')) + // [EndExclude bottom_navigation] + } + // [End bottom_navigation] + .height(500) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.BottomTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/ContentWillChange.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/ContentWillChange.ets new file mode 100644 index 0000000000000000000000000000000000000000..a414fd27b1237f0e2c65060567d6c0802ceabf1c --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/ContentWillChange.ets @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; + +// [Start switch_the_tab_to_a_specific_tab] +@Entry +@Component +export struct ContentWillChange { + scroller: Scroller = new Scroller(); + @State currentIndex: number = 2; + // [StartExclude switch_the_tab_to_a_specific_tab] + @State currentIndexTwo: number = 2; + @State currentIndexThree: number = 2; + private controller: TabsController = new TabsController(); + private controllerTwo: TabsController = new TabsController(); + // [EndExclude switch_the_tab_to_a_specific_tab] + + @Builder + tabBuilder(title: ResourceStr, targetIndex: number) { + Column() { + Text(title) + .fontColor(this.currentIndex === targetIndex ? '#F111C1' : '#6B6B6B') + } + } + + // [StartExclude switch_the_tab_to_a_specific_tab] + @Builder + tabBuilderTwo(title: ResourceStr, targetIndex: number) { + Column() { + Text(title) + .fontColor(this.currentIndexTwo === targetIndex ? '#F111C1' : '#6B6B6B') + } + } + + @Builder + tabBuilderThree(title: ResourceStr, targetIndex: number) { + Column() { + Text(title) + .fontColor(this.currentIndexThree === targetIndex ? '#F111C1' : '#6B6B6B') + } + } + // [EndExclude switch_the_tab_to_a_specific_tab] + + build() { + // [StartExclude switch_the_tab_to_a_specific_tab] + NavDestination() { + Scroll(this.scroller) { + // [EndExclude switch_the_tab_to_a_specific_tab] + Column({ space: 12 }) { + // [StartExclude switch_the_tab_to_a_specific_tab] + ComponentCard({ title: $r('app.string.ContentWillChange_titleContentAndTabSync') }) { + // [EndExclude switch_the_tab_to_a_specific_tab] + Tabs({ barPosition: BarPosition.End }) { + TabContent() { + // [StartExclude switch_the_tab_to_a_specific_tab] + Text($r('app.string.homepage_content')) + .fontSize(30) + // [EndExclude switch_the_tab_to_a_specific_tab] + } + .backgroundColor(Color.Blue) + .tabBar(this.tabBuilder($r('app.string.homepage'), 0)) + + TabContent() { + // [StartExclude switch_the_tab_to_a_specific_tab] + Text($r('app.string.discover_content')) + .fontSize(30) + // [EndExclude switch_the_tab_to_a_specific_tab] + } + .backgroundColor(Color.Green) + .tabBar(this.tabBuilder($r('app.string.discover'), 1)) + + TabContent() { + // [StartExclude switch_the_tab_to_a_specific_tab] + Text($r('app.string.recommend_content')) + .fontSize(30) + // [EndExclude switch_the_tab_to_a_specific_tab] + } + .backgroundColor(Color.Yellow) + .tabBar(this.tabBuilder($r('app.string.recommend'), 2)) + + TabContent() { + // [StartExclude switch_the_tab_to_a_specific_tab] + Text($r('app.string.mine_content')) + .fontSize(30) + // [EndExclude switch_the_tab_to_a_specific_tab] + } + .backgroundColor(Color.Orange) + .tabBar(this.tabBuilder($r('app.string.mine'), 3)) + } + .animationDuration(0) + .height(300) + .onChange((index: number) => { + this.currentIndex = index; + }) + } + + ComponentCard({ title: $r('app.string.ContentWillChange_titleSpecifiedTab') }) { + Column({ space: 8 }) { + // [Start content_associated_with_tab] + Tabs({ barPosition: BarPosition.End, index: this.currentIndexTwo, controller: this.controller }) { + // [StartExclude content_associated_with_tab] + TabContent() { + Text($r('app.string.homepage_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar(this.tabBuilderTwo($r('app.string.homepage'), 0)) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar(this.tabBuilderTwo($r('app.string.discover'), 1)) + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar(this.tabBuilderTwo($r('app.string.recommend'), 2)) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar(this.tabBuilderTwo($r('app.string.mine'), 3)) + // [EndExclude content_associated_with_tab] + } + .animationDuration(0) + .height(300) + .onChange((index: number) => { + this.currentIndexTwo = index; + }) + + Button($r('app.string.ContentWillChange_changeIndex')).width('50%') + .onClick(() => { + this.currentIndexTwo = (this.currentIndexTwo + 1) % 4; + }) + + Button('changeIndex').width('50%') + .onClick(() => { + let index = (this.currentIndexTwo + 1) % 4; + this.controller.changeIndex(index); + }) + // [End content_associated_with_tab] + } + } + + ComponentCard({ title: $r('app.string.ContentWillChange_titleInterception') }) { + Column({ space: 8 }) { + // [Start custom_page_toggle_interception_events] + Tabs({ barPosition: BarPosition.End, index: this.currentIndexThree, controller: this.controllerTwo }) { + // [StartExclude custom_page_toggle_interception_events] + TabContent() { + Text($r('app.string.homepage_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar(this.tabBuilderThree($r('app.string.homepage'), 0)) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar(this.tabBuilderThree($r('app.string.discover'), 1)) + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar(this.tabBuilderThree($r('app.string.recommend'), 2)) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar(this.tabBuilderThree($r('app.string.mine'), 3)) + // [EndExclude custom_page_toggle_interception_events] + } + // [StartExclude custom_page_toggle_interception_events] + .animationDuration(0) + .height(300) + // [EndExclude custom_page_toggle_interception_events] + .onChange((index: number) => { + this.currentIndexThree = index; + }) + .onContentWillChange((currentIndex, comingIndex) => { + if (comingIndex == 2) { + return false; + } + return true; + }) + // [End custom_page_toggle_interception_events] + + Button($r('app.string.ContentWillChange_changeIndex')).width('50%') + .onClick(() => { + this.currentIndexThree = (this.currentIndexThree + 1) % 4; + }) + + Button('changeIndex').width('50%') + .onClick(() => { + let index = (this.currentIndexThree + 1) % 4; + this.controllerTwo.changeIndex(index); + }) + } + } + } + .width('100%') + .padding({ left: 12, right: 12 }) + } + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ContentWillChange_title')) + } +} +// [End switch_the_tab_to_a_specific_tab] \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/CustomTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/CustomTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..de0d4c16d7d5f6af6b3eb05f724c3e9b1c2809c7 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/CustomTabBar.ets @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct CustomTabBar { + // [Start custom_tab_bar_style] + @State currentIndex: number = 0; + + @Builder + tabBuilder(title: ResourceStr, targetIndex: number, selectedImg: Resource, normalImg: Resource) { + Column() { + Image(this.currentIndex === targetIndex ? selectedImg : normalImg) + .size({ width: 25, height: 25 }) + Text(title) + .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B') + } + .width('100%') + .height(50) + .justifyContent(FlexAlign.Center) + } + // [End custom_tab_bar_style] + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.CustomTabBar_titleExample') }) { + Tabs({ barPosition: BarPosition.End }) { + TabContent() { + Text($r('app.string.internet_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar(this.tabBuilder($r('app.string.internet'), + 0, + $r('sys.media.ohos_ic_public_web'), + $r('sys.media.ohos_ic_public_web'))) + + TabContent() { + Text($r('app.string.album_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar(this.tabBuilder($r('app.string.album'), + 1, + $r('sys.media.ohos_ic_public_albums'), + $r('sys.media.ohos_ic_public_albums'))) + + TabContent() { + Text($r('app.string.video_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar(this.tabBuilder($r('app.string.video'), + 2, + $r('sys.media.ohos_ic_public_video'), + $r('sys.media.ohos_ic_public_video'))) + + // [Start set_custom_tab_bar_style] + TabContent() { + Text($r('app.string.more_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar(this.tabBuilder($r('app.string.more'), + 3, + $r('sys.media.ohos_ic_public_drawer_open'), + $r('sys.media.ohos_ic_public_drawer_open'))) + // [End set_custom_tab_bar_style] + }.height(500) + .onChange((index: number) => { + this.currentIndex = index; // 监听索引index的变化,实现页签内容的切换。 + }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.CustomTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/FixedTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/FixedTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..a786d084a857b391180a9d90a75183ba0414f435 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/FixedTabBar.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct FixedTabBar { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.FixedTabBar_titleExample') }) { + // [Start fixed_tab_bar] + Tabs({ barPosition: BarPosition.End }) { + // [StartExclude fixed_tab_bar] + TabContent() { + Text($r('app.string.homepage_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar($r('app.string.homepage')) + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar($r('app.string.recommend')) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar($r('app.string.discover')) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar($r('app.string.mine')) + // [EndExclude fixed_tab_bar] + } + // [StartExclude fixed_tab_bar] + .height(500) + // [EndExclude fixed_tab_bar] + .barMode(BarMode.Fixed) + // [End fixed_tab_bar] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.FixedTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/ScrollableTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/ScrollableTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..ef93f632f6f18c893105e7fb735219eddd5f55cb --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/ScrollableTabBar.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 { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct ScrollableTabBar { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.ScrollableTabBar_titleExample') }) { + // [Start scrollable_tab_bar] + Tabs({ barPosition: BarPosition.Start }) { + // [StartExclude scrollable_tab_bar] + TabContent() { + Text($r('app.string.FocusOn_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar($r('app.string.FocusOn')) + + TabContent() { + Text($r('app.string.video_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar($r('app.string.video')) + + TabContent() { + Text($r('app.string.game_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar($r('app.string.game')) + + TabContent() { + Text($r('app.string.digit_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar($r('app.string.digit')) + + TabContent() { + Text($r('app.string.technology_content')) + .fontSize(30) + } + .backgroundColor(Color.Pink) + .tabBar($r('app.string.technology')) + + TabContent() { + Text($r('app.string.sport_content')) + .fontSize(30) + } + .backgroundColor(Color.Gray) + .tabBar($r('app.string.sport')) + + TabContent() { + Text($r('app.string.film_content')) + .fontSize(30) + } + .backgroundColor(Color.Brown) + .tabBar($r('app.string.film')) + + TabContent() { + Text($r('app.string.humanities_content')) + .fontSize(30) + } + .backgroundColor(Color.Red) + .tabBar($r('app.string.humanities')) + // [EndExclude scrollable_tab_bar] + } + // [StartExclude scrollable_tab_bar] + .barWidth(250) + .height(500) + // [EndExclude scrollable_tab_bar] + .barMode(BarMode.Scrollable) + // [End scrollable_tab_bar] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.ScrollableTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/SideTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/SideTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..70f2bedb836d1787b542c25a3a40a207943121c7 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/SideTabBar.ets @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SideTabBar { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SideTabBar_titleExample') }) { + // [Start side_navigation] + Tabs({ barPosition: BarPosition.Start }) { + // [StartExclude side_navigation] + TabContent() { + Text($r('app.string.homepage_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar($r('app.string.homepage')) + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar($r('app.string.recommend')) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar($r('app.string.discover')) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar($r('app.string.mine')) + // [EndExclude side_navigation] + } + // [StartExclude side_navigation] + .height(200) + // [EndExclude side_navigation] + .vertical(true) + .barWidth(100) + .barHeight(200) + // [End side_navigation] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SideTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/SwipeLockedTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/SwipeLockedTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..abb21c01b947663fde1ec16839c73dd40b0912c0 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/SwipeLockedTabBar.ets @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct SwipeLockedTabBar { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.SwipeLockedTabBar_titleExample') }) { + // [Start swipe_locked_tab_bar] + Tabs({ barPosition: BarPosition.End }) { + TabContent() { + Column() { + Tabs() { + // 顶部导航栏内容 + // [StartExclude swipe_locked_tab_bar] + TabContent() { + Text($r('app.string.FocusOn_content')) + .fontSize(30) + } + .tabBar($r('app.string.FocusOn')) + + TabContent() { + Text($r('app.string.video_content')) + .fontSize(30) + } + .tabBar($r('app.string.video')) + + TabContent() { + Text($r('app.string.game_content')) + .fontSize(30) + } + .tabBar($r('app.string.game')) + + TabContent() { + Text($r('app.string.digit_content')) + .fontSize(30) + } + .tabBar($r('app.string.digit')) + + TabContent() { + Text($r('app.string.technology_content')) + .fontSize(30) + } + .tabBar($r('app.string.technology')) + } + } + .backgroundColor('#ffffc6d1') + .width('100%') + } + .tabBar($r('app.string.homepage')) + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar($r('app.string.recommend')) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar($r('app.string.discover')) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar($r('app.string.mine')) + // [EndExclude swipe_locked_tab_bar] + } + // [StartExclude swipe_locked_tab_bar] + .height(500) + // [EndExclude swipe_locked_tab_bar] + .scrollable(false) + // [End swipe_locked_tab_bar] + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.SwipeLockedTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/TabsLayout.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/TabsLayout.ets new file mode 100644 index 0000000000000000000000000000000000000000..2ab0bde038280cc905ab9ff1b135dbf3d21deae8 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/TabsLayout.ets @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct TabsLayout { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.TabsLayout_titleExample') }) { + // [Start basic_layout_displays_many_contents] + Tabs() { + // [Start basic_layout_displays_one_content] + TabContent() { + Text($r('app.string.homepage_content')) + .fontSize(30) + } + .tabBar($r('app.string.homepage')) + // [End basic_layout_displays_one_content] + + TabContent() { + Text($r('app.string.recommend_content')) + .fontSize(30) + } + .tabBar($r('app.string.recommend')) + + TabContent() { + Text($r('app.string.discover_content')) + .fontSize(30) + } + .tabBar($r('app.string.discover')) + + TabContent() { + Text($r('app.string.mine_content')) + .fontSize(30) + } + .tabBar($r('app.string.mine')) + // [StartExclude basic_layout_displays_many_contents] + }.height(300) + // [EndExclude basic_layout_displays_many_contents] + } + // [End basic_layout_displays_many_contents] + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.TabsLayout_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/TopTabBar.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/TopTabBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..ac40d162d18cf06d0ecfae41db5afd64839dd0b2 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/TopTabBar.ets @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; + +@Entry +@Component +export struct TopTabBar { + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.TopTabBar_titleExample') }) { + // [Start top_navigation] + Tabs({ barPosition: BarPosition.Start }) { + // [StartExclude top_navigation] + TabContent() { + Text($r('app.string.FocusOn_content')) + .fontSize(30) + } + .backgroundColor(Color.Blue) + .tabBar($r('app.string.FocusOn')) + + TabContent() { + Text($r('app.string.video_content')) + .fontSize(30) + } + .backgroundColor(Color.Green) + .tabBar($r('app.string.video')) + + TabContent() { + Text($r('app.string.game_content')) + .fontSize(30) + } + .backgroundColor(Color.Yellow) + .tabBar($r('app.string.game')) + + TabContent() { + Text($r('app.string.digit_content')) + .fontSize(30) + } + .backgroundColor(Color.Orange) + .tabBar($r('app.string.digit')) + + TabContent() { + Text($r('app.string.technology_content')) + .fontSize(30) + } + .backgroundColor(Color.Pink) + .tabBar($r('app.string.technology')) + }.height(500) + // [EndExclude top_navigation] + } + // [End top_navigation] + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.TopTabBar_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b601f6080cca995f0b2a9c9f1acdb62245de2a22 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/tabs/index.ets @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { AgeFriendlyTabs } from './AgeFriendlyTabs'; +import { BottomTabBar } from './BottomTabBar'; +import { CompletedRoutableCard } from '../../common/Card'; +import { ContentWillChange } from './ContentWillChange'; +import { CustomTabBar } from './CustomTabBar'; +import { FixedTabBar } from './FixedTabBar'; +import { Route } from '../../common/Route'; +import { ScrollableTabBar } from './ScrollableTabBar'; +import { SideTabBar } from './SideTabBar'; +import { SwipeLockedTabBar } from './SwipeLockedTabBar'; +import { TabsLayout } from './TabsLayout'; +import { TopTabBar } from './TopTabBar'; +import resource from '../../common/resource'; + +export const TABS_ROUTE_PREFIX: string = 'tabs'; + +const routes: Route[] = [ + { + name: `${TABS_ROUTE_PREFIX}/TabsLayout`, + title: resource.resourceToString($r('app.string.TabsLayout_title')), + description: $r('app.string.TabsLayout_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/BottomTabBar`, + title: resource.resourceToString($r('app.string.BottomTabBar_title')), + description: $r('app.string.BottomTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/TopTabBar`, + title: resource.resourceToString($r('app.string.TopTabBar_title')), + description: $r('app.string.TopTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/SideTabBar`, + title: resource.resourceToString($r('app.string.SideTabBar_title')), + description: $r('app.string.SideTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/SwipeLockedTabBar`, + title: resource.resourceToString($r('app.string.SwipeLockedTabBar_title')), + description: $r('app.string.SwipeLockedTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/FixedTabBar`, + title: resource.resourceToString($r('app.string.FixedTabBar_title')), + description: $r('app.string.FixedTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/ScrollableTabBar`, + title: resource.resourceToString($r('app.string.ScrollableTabBar_title')), + description: $r('app.string.ScrollableTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/CustomTabBar`, + title: resource.resourceToString($r('app.string.CustomTabBar_title')), + description: $r('app.string.CustomTabBar_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/ContentWillChange`, + title: resource.resourceToString($r('app.string.ContentWillChange_title')), + description: $r('app.string.ContentWillChange_description') + }, + { + name: `${TABS_ROUTE_PREFIX}/AgeFriendlyTabs`, + title: resource.resourceToString($r('app.string.AgeFriendlyTabs_title')), + description: $r('app.string.AgeFriendlyTabs_description') + } +]; + +@Builder +export function tabsDestination(name: string) { + if (name === TABS_ROUTE_PREFIX) { + TabsExample(); + } else if (name === routes[0].name) { + TabsLayout(); + } else if (name === routes[1].name) { + BottomTabBar(); + } else if (name === routes[2].name) { + TopTabBar(); + } else if (name === routes[3].name) { + SideTabBar(); + } else if (name === routes[4].name) { + SwipeLockedTabBar(); + } else if (name === routes[5].name) { + FixedTabBar(); + } else if (name === routes[6].name) { + ScrollableTabBar(); + } else if (name === routes[7].name) { + CustomTabBar(); + } else if (name === routes[8].name) { + ContentWillChange(); + } else if (name === routes[9].name) { + AgeFriendlyTabs(); + } +} + +@Entry +@Component +struct TabsExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('Tabs', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDataSource.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..3dfc468dab8a710c503ab4537d43e56fb5ce2bd0 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDataSource.ets @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// 实现IDataSource接口的对象,用于瀑布流组件加载数据 +export class WaterFlowDataSource implements IDataSource { + private dataArray: number[] = []; + private listeners: DataChangeListener[] = []; + + constructor(count: number) { + for (let i = 0; i < count; i++) { + this.dataArray.push(i); + } + } + + // 获取索引对应的数据 + public getData(index: number): number { + return this.dataArray[index]; + } + + // 通知控制器数据重新加载 + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }) + } + + // 通知控制器数据增加 + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }) + } + + // 通知控制器数据变化 + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }) + } + + // 通知控制器数据删除 + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }) + } + + // 通知控制器数据位置变化 + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }) + } + + // 获取数据总数 + public totalCount(): number { + return this.dataArray.length; + } + + // 注册改变数据的控制器 + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener); + } + } + + // 注销改变数据的控制器 + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener) + if (pos >= 0) { + this.listeners.splice(pos, 1); + } + } + + // 增加数据 + public add1stItem(): void { + this.dataArray.splice(0, 0, this.dataArray.length); + this.notifyDataAdd(0); + } + + // 在数据尾部增加一个元素 + public addLastItem(): void { + this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length); + this.notifyDataAdd(this.dataArray.length - 1); + } + + public addNewItems(count: number): void { + for (let i = 0; i < count; i++) { + this.dataArray.push(this.dataArray.length); + this.notifyDataAdd(this.dataArray.length - 1); + } + } + + // 在指定索引位置增加一个元素 + public addItem(index: number): void { + this.dataArray.splice(index, 0, this.dataArray.length); + this.notifyDataAdd(index); + } + + // 删除第一个元素 + public delete1stItem(): void { + this.dataArray.splice(0, 1); + this.notifyDataDelete(0); + } + + // 删除第二个元素 + public delete2ndItem(): void { + this.dataArray.splice(1, 1); + this.notifyDataDelete(1); + } + + // 删除最后一个元素 + public deleteLastItem(): void { + this.dataArray.splice(-1, 1); + this.notifyDataDelete(this.dataArray.length); + } + + // 在指定索引位置增加一个元素 + public deleteItem(index: number): void { + this.dataArray.splice(index, 1); + this.notifyDataDelete(index); + } + + // 重新加载数据 + public reload(): void { + this.dataArray.splice(1, 1); + this.dataArray.splice(3, 2); + this.notifyDataReload(); + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDynamicSwitchover.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDynamicSwitchover.ets new file mode 100644 index 0000000000000000000000000000000000000000..6c7ccb83c5a000e1af44dc02091fbe3b1475b9ce --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDynamicSwitchover.ets @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; +import { WaterFlowDataSource } from './WaterFlowDataSource' +import { image } from '@kit.ImageKit'; + +@Reusable +@Component +struct ReusableFlowItem { + @State item: number = 0; + + // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容 + aboutToReuse(params: Record) { + this.item = params.item; + } + + build() { + Column() { + Text('FlowItem' + this.item).fontSize(16).height('16') + Image('res/waterFlow(' + this.item % 5 + ').JPG') + .objectFit(ImageFit.Fill) + .width('100%') + .layoutWeight(1) + } + } +} + +@Reusable +@Component +struct ReusableListItem { + @State item: number = 0; + + aboutToReuse(params: Record) { + this.item = params.item; + } + + build() { + Row() { + Image('res/waterFlow(' + this.item % 5 + ').JPG') + .objectFit(ImageFit.Fill) + .height(100) + .aspectRatio(1) + Text('N' + this.item).fontSize(12).height('16').layoutWeight(1).textAlign(TextAlign.Center) + } + } +} + +@Entry +@Component +export struct WaterFlowDynamicSwitchover { + minSize: number = 80; + maxSize: number = 180; + colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; + dataSource: WaterFlowDataSource = new WaterFlowDataSource(100); + private itemWidthArray: number[] = []; + private itemHeightArray: number[] = []; + @State columns: number = 2; + @State waterflowScale: number = 1; + @State imageScale: number = 1; + @State waterFlowOpacity: number = 1; + @State waterflowSnapshot: image.PixelMap | undefined = undefined; + private columnChanged: boolean = false; + private oldColumn: number = this.columns; + private pinchTime: number = 0; + private gridItems: number[] = []; + + // 计算FlowItem宽/高 + getSize() { + let ret = Math.floor(Math.random() * this.maxSize); + return (ret > this.minSize ? ret : this.minSize); + } + + // 设置FlowItem的宽/高数组 + setItemSizeArray() { + for (let i = 0; i < 100; i++) { + this.itemWidthArray.push(this.getSize()); + this.itemHeightArray.push(this.getSize()); + } + } + + aboutToAppear() { + // 读取上次最后切换到到列数 + let lastCount = AppStorage.get('columnsCount'); + if (typeof lastCount != 'undefined') { + this.columns = lastCount; + } + this.setItemSizeArray(); + for (let i = 0; i < 15; ++i) { + this.gridItems.push(i); + } + } + + // 根据缩放阈值改变列数,触发WaterFlow重新布局 + changeColumns(scale: number) { + if (scale > (this.columns / (this.columns - 0.5)) && this.columns > 1) { + this.columns--; + this.columnChanged = true; + } else if (scale < 1 && this.columns < 4) { + this.columns++; + this.columnChanged = true; + } + } + + @Builder + itemFoot() { + Row() { + LoadingProgress() + .color(Color.Blue).height(50).aspectRatio(1).width('20%') + Text(`正在加载`) + .fontSize(20) + .width('30%') + .height(50) + .align(Alignment.Center) + .margin({ top: 2 }) + }.width('100%').justifyContent(FlexAlign.Center) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.WaterFlowDynamicSwitchover_title') }) { + Column({ space: 2 }) { + Button('切换列数').fontSize(20).onClick(() => { + if (this.columns === 2) { + this.columns = 1; + } else { + this.columns = 2; + } + }) + WaterFlow({ layoutMode: WaterFlowLayoutMode.SLIDING_WINDOW }) { + LazyForEach(this.dataSource, (item: number) => { + FlowItem() { + if (this.columns === 1) { + ReusableListItem({ item: item }) + } else { + ReusableFlowItem({ item: item }) + } + } + .width('100%') + .aspectRatio(this.columns === 2 ? this.itemHeightArray[item % 100] / this.itemWidthArray[item % 100] : 0) + .backgroundColor(this.colors[item % 5]) + }, (item: string) => item) + } + .columnsTemplate('1fr '.repeat(this.columns)) + .backgroundColor(0xFAEEE0) + .width('100%') + .height('100%') + .layoutWeight(1) + // 即将触底时提前增加数据 + .onScrollIndex((first: number, last: number) => { + if (last + 20 >= this.dataSource.totalCount()) { + setTimeout(() => { + this.dataSource.addNewItems(100); + }, 1000); + } + }) + } + } + } + .width('100%') + .height('100%') + } + .backgroundColor('#f1f2f3') + .title($r('app.string.WaterFlowDynamicSwitchover_title')) + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowGroupingMixing.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowGroupingMixing.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f5fcc388c75a2ff187f8ffa7f5d49b1fd8b1488 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowGroupingMixing.ets @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { ComponentCard } from '../../common/Card'; +import { WaterFlowDataSource } from './WaterFlowDataSource' +import { image } from '@kit.ImageKit'; + +@Reusable +@Component +struct ReusableFlowItem { + @State item: number = 0; + + // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容 + aboutToReuse(params: Record) { + this.item = params.item; + } + + build() { + Stack({ alignContent: Alignment.Center }) { + Text('FlowItem' + this.item).fontSize(14).height('16') + Image('res/waterFlow (' + this.item % 5 + ').JPG') + .objectFit(ImageFit.Fill) + .width('100%') + .layoutWeight(1) + } + } +} + +@Entry +@Component +export struct WaterFlowGroupingMixing { + minSize: number = 80; + maxSize: number = 180; + colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; + dataSource: WaterFlowDataSource = new WaterFlowDataSource(100); + private itemWidthArray: number[] = []; + private itemHeightArray: number[] = []; + @State columns: number = 2; + @State waterflowScale: number = 1; + @State imageScale: number = 1; + @State waterFlowOpacity: number = 1; + @State waterflowSnapshot: image.PixelMap | undefined = undefined; + private columnChanged: boolean = false; + private oldColumn: number = this.columns; + private pinchTime: number = 0; + private gridItems: number[] = []; + + // 计算FlowItem宽/高 + getSize() { + let ret = Math.floor(Math.random() * this.maxSize); + return (ret > this.minSize ? ret : this.minSize); + } + + // 设置FlowItem的宽/高数组 + setItemSizeArray() { + for (let i = 0; i < 100; i++) { + this.itemWidthArray.push(this.getSize()); + this.itemHeightArray.push(this.getSize()); + } + } + + aboutToAppear() { + // 读取上次最后切换到到列数 + let lastCount = AppStorage.get('columnsCount'); + if (typeof lastCount != 'undefined') { + this.columns = lastCount; + } + this.setItemSizeArray(); + for (let i = 0; i < 15; ++i) { + this.gridItems.push(i); + } + } + + // 根据缩放阈值改变列数,触发WaterFlow重新布局 + changeColumns(scale: number) { + if (scale > (this.columns / (this.columns - 0.5)) && this.columns > 1) { + this.columns--; + this.columnChanged = true; + } else if (scale < 1 && this.columns < 4) { + this.columns++; + this.columnChanged = true; + } + } + + @Builder + itemFoot() { + Row() { + LoadingProgress() + .color(Color.Blue).height(50).aspectRatio(1).width('20%') + Text(`正在加载`) + .fontSize(20) + .width('30%') + .height(50) + .align(Alignment.Center) + .margin({ top: 2 }) + }.width('100%').justifyContent(FlexAlign.Center) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.WaterFlowGroupingMixing_title') }) { + List({ space: 10 }) { + ListItem() { + Text('List').fontSize(14).height(16).margin(3) + } + + ListItem() { + Column() { + Text('Grid in ListItem').fontSize(12).height(16).margin(3) + + Grid() { + ForEach(this.gridItems, (day: number) => { + GridItem() { + Text('GridItem').fontSize(10).height(16) + }.backgroundColor(0xFFC0CB) + }, (day: number) => day.toString()) + } + .height('30%') + .rowsGap(5) + .columnsGap(5) + .columnsTemplate('1fr '.repeat(5)) + .rowsTemplate('1fr '.repeat(3)) + .width('95%') + }.borderWidth(3) + } + + ListItem() { + Column() { + Text('WaterFlow in ListItem').fontSize(14).height(16).margin(3) + WaterFlow({ layoutMode: WaterFlowLayoutMode.SLIDING_WINDOW }) { + LazyForEach(this.dataSource, (item: number) => { + FlowItem() { + ReusableFlowItem({ item: item }) + } + .width('100%') + .aspectRatio(this.columns === 2 ? this.itemHeightArray[item % 100] / this.itemWidthArray[item % 100] : 0) + .backgroundColor(this.colors[item % 5]) + }, (item: string) => item) + } + .columnsTemplate('1fr '.repeat(this.columns)) + .backgroundColor(0xFAEEE0) + .height('100%') + .layoutWeight(1) + // 即将触底时提前增加数据 + .onScrollIndex((first: number, last: number) => { + if (last + 20 >= this.dataSource.totalCount()) { + setTimeout(() => { + this.dataSource.addNewItems(100); + }, 1000) + } + }) + .width('95%') + }.borderWidth(3) + } + }.borderWidth(3) + .width('98%') + .alignListItem(ListItemAlign.Center).scrollBar(BarState.Off) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.WaterFlowGroupingMixing_title')) + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrolling.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrolling.ets new file mode 100644 index 0000000000000000000000000000000000000000..090bdf39b81bc3ba995ca1617cc95492d8cdcb44 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrolling.ets @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; +import { WaterFlowDataSource } from './WaterFlowDataSource' +import { image } from '@kit.ImageKit'; + +@Reusable +@Component +struct ReusableFlowItem { + @State item: number = 0; + + // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容 + aboutToReuse(params: Record) { + this.item = params.item; + } + + build() { + Column() { + Text('FlowItem' + this.item).fontSize(16).height('16') + Image('res/waterFlow(' + this.item % 5 + ').JPG') + .objectFit(ImageFit.Fill) + .width('100%') + .layoutWeight(1) + } + } +} + +@Entry +@Component +export struct WaterFlowInfiniteScrolling { + minSize: number = 80; + maxSize: number = 180; + colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; + dataSource: WaterFlowDataSource = new WaterFlowDataSource(100); + private itemWidthArray: number[] = []; + private itemHeightArray: number[] = []; + @State columns: number = 2; + @State waterflowScale: number = 1; + @State imageScale: number = 1; + @State waterFlowOpacity: number = 1; + @State waterflowSnapshot: image.PixelMap | undefined = undefined; + private columnChanged: boolean = false; + private oldColumn: number = this.columns; + private pinchTime: number = 0; + private gridItems: number[] = []; + + // 计算FlowItem宽/高 + getSize() { + let ret = Math.floor(Math.random() * this.maxSize); + return (ret > this.minSize ? ret : this.minSize); + } + + // 设置FlowItem的宽/高数组 + setItemSizeArray() { + for (let i = 0; i < 100; i++) { + this.itemWidthArray.push(this.getSize()); + this.itemHeightArray.push(this.getSize()); + } + } + + aboutToAppear() { + // 读取上次最后切换到到列数 + let lastCount = AppStorage.get('columnsCount'); + if (typeof lastCount != 'undefined') { + this.columns = lastCount; + } + this.setItemSizeArray(); + for (let i = 0; i < 15; ++i) { + this.gridItems.push(i); + } + } + + // 根据缩放阈值改变列数,触发WaterFlow重新布局 + changeColumns(scale: number) { + if (scale > (this.columns / (this.columns - 0.5)) && this.columns > 1) { + this.columns--; + this.columnChanged = true; + } else if (scale < 1 && this.columns < 4) { + this.columns++; + this.columnChanged = true; + } + } + + @Builder + itemFoot() { + Row() { + LoadingProgress() + .color(Color.Blue).height(50).aspectRatio(1).width('20%') + Text(`正在加载`) + .fontSize(20) + .width('30%') + .height(50) + .align(Alignment.Center) + .margin({ top: 2 }) + }.width('100%').justifyContent(FlexAlign.Center) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.WaterFlowInfiniteScrolling_title') }) { + WaterFlow({ footer: this.itemFoot(), layoutMode: WaterFlowLayoutMode.SLIDING_WINDOW }) { + LazyForEach(this.dataSource, (item: number) => { + FlowItem() { + ReusableFlowItem({ item: item }) + } + .width('100%') + .aspectRatio(this.itemHeightArray[item % 100] / this.itemWidthArray[item%100]) + .backgroundColor(this.colors[item % 5]) + }, (item: string) => item) + } + .columnsTemplate('1fr '.repeat(this.columns)) + .backgroundColor(0xFAEEE0) + .width('100%') + .height('100%') + .layoutWeight(1) + // 触底加载数据 + .onReachEnd(() => { + setTimeout(() => { + for (let i = 0; i < 100; i++) { + this.dataSource.addLastItem(); + } + }, 1000) + }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.WaterFlowInfiniteScrolling_title')) + } +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrollingEarly.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrollingEarly.ets new file mode 100644 index 0000000000000000000000000000000000000000..162cb8e756fd1ce79512599c73e712d7ab1f0d1c --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrollingEarly.ets @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentCard } from '../../common/Card'; +import { WaterFlowDataSource } from './WaterFlowDataSource' +import { image } from '@kit.ImageKit'; + +@Reusable +@Component +struct ReusableFlowItem { + @State item: number = 0; + + // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容 + aboutToReuse(params: Record) { + this.item = params.item; + } + + build() { + Column() { + Text('FlowItem' + this.item).fontSize(16).height('16') + Image('res/waterFlow(' + this.item % 5 + ').JPG') + .objectFit(ImageFit.Fill) + .width('100%') + .layoutWeight(1) + } + } +} + +@Entry +@Component +export struct WaterFlowInfiniteScrollingEarly { + minSize: number = 80; + maxSize: number = 180; + colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; + dataSource: WaterFlowDataSource = new WaterFlowDataSource(100); + private itemWidthArray: number[] = []; + private itemHeightArray: number[] = []; + @State columns: number = 2; + @State waterflowScale: number = 1; + @State imageScale: number = 1; + @State waterFlowOpacity: number = 1; + @State waterflowSnapshot: image.PixelMap | undefined = undefined; + private columnChanged: boolean = false; + private oldColumn: number = this.columns; + private pinchTime: number = 0; + private gridItems: number[] = []; + + // 计算FlowItem宽/高 + getSize() { + let ret = Math.floor(Math.random() * this.maxSize); + return (ret > this.minSize ? ret : this.minSize); + } + + // 设置FlowItem的宽/高数组 + setItemSizeArray() { + for (let i = 0; i < 100; i++) { + this.itemWidthArray.push(this.getSize()); + this.itemHeightArray.push(this.getSize()); + } + } + + aboutToAppear() { + // 读取上次最后切换到到列数 + let lastCount = AppStorage.get('columnsCount'); + if (typeof lastCount != 'undefined') { + this.columns = lastCount; + } + this.setItemSizeArray(); + for (let i = 0; i < 15; ++i) { + this.gridItems.push(i); + } + } + + // 根据缩放阈值改变列数,触发WaterFlow重新布局 + changeColumns(scale: number) { + if (scale > (this.columns / (this.columns - 0.5)) && this.columns > 1) { + this.columns--; + this.columnChanged = true; + } else if (scale < 1 && this.columns < 4) { + this.columns++; + this.columnChanged = true; + } + } + + @Builder + itemFoot() { + Row() { + LoadingProgress() + .color(Color.Blue).height(50).aspectRatio(1).width('20%') + Text(`正在加载`) + .fontSize(20) + .width('30%') + .height(50) + .align(Alignment.Center) + .margin({ top: 2 }) + }.width('100%').justifyContent(FlexAlign.Center) + } + + build() { + NavDestination() { + Column({ space: 12 }) { + ComponentCard({ title: $r('app.string.WaterFlowInfiniteScrollingEarly_title') }) { + WaterFlow({ layoutMode: WaterFlowLayoutMode.SLIDING_WINDOW }) { + LazyForEach(this.dataSource, (item: number) => { + FlowItem() { + ReusableFlowItem({ item: item }) + } + .width('100%') + .aspectRatio(this.itemHeightArray[item % 100] / this.itemWidthArray[item%100]) + .backgroundColor(this.colors[item % 5]) + }, (item: string) => item) + } + .columnsTemplate('1fr '.repeat(this.columns)) + .backgroundColor(0xFAEEE0) + .width('100%') + .height('100%') + .layoutWeight(1) + // 即将触底时提前增加数据 + .onScrollIndex((first: number, last: number) => { + if (last + 20 >= this.dataSource.totalCount()) { + setTimeout(() => { + this.dataSource.addNewItems(100); + }, 1000); + } + }) + } + } + .width('100%') + .height('100%') + .padding({ left: 12, right: 12 }) + } + .backgroundColor('#f1f2f3') + .title($r('app.string.WaterFlowInfiniteScrollingEarly_title')) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/index.ets b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..d7c2f53083ee3356cb30e453c41c0ed9b9b3bbfc --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/ets/pages/waterFlow/index.ets @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CompletedRoutableCard } from '../../common/Card'; +import { Route } from '../../common/Route'; +import { WaterFlowInfiniteScrolling } from './WaterFlowInfiniteScrolling'; +import { WaterFlowInfiniteScrollingEarly } from './WaterFlowInfiniteScrollingEarly'; +import { WaterFlowGroupingMixing } from './WaterFlowGroupingMixing'; +import { WaterFlowDynamicSwitchover } from './WaterFlowDynamicSwitchover'; +import resource from '../../common/resource'; + +export const WATERFLOW_ROUTE_PREFIX: string = 'waterFlow'; + +const routes: Route[] = [ + { + name: `${WATERFLOW_ROUTE_PREFIX}/WaterFlowInfiniteScrolling`, + title: resource.resourceToString($r('app.string.WaterFlowInfiniteScrolling_title')), + description: $r('app.string.WaterFlowInfiniteScrolling_description') + }, + { + name: `${WATERFLOW_ROUTE_PREFIX}/WaterFlowInfiniteScrollingEarly`, + title: resource.resourceToString($r('app.string.WaterFlowInfiniteScrollingEarly_title')), + description: $r('app.string.WaterFlowInfiniteScrollingEarly_description') + }, + { + name: `${WATERFLOW_ROUTE_PREFIX}/WaterFlowGroupingMixing`, + title: resource.resourceToString($r('app.string.WaterFlowGroupingMixing_title')), + description: $r('app.string.WaterFlowGroupingMixing_description') + }, + { + name: `${WATERFLOW_ROUTE_PREFIX}/WaterFlowDynamicSwitchover`, + title: resource.resourceToString($r('app.string.WaterFlowDynamicSwitchover_title')), + description: $r('app.string.WaterFlowDynamicSwitchover_description') + } + +]; + +@Builder +export function waterFlowDestination(name: string) { + if (name === WATERFLOW_ROUTE_PREFIX) { + WaterFlowExample(); + } else if (name === routes[0].name) { + WaterFlowInfiniteScrolling(); + } else if (name === routes[1].name) { + WaterFlowInfiniteScrollingEarly(); + } else if (name === routes[2].name) { + WaterFlowGroupingMixing(); + } else if (name === routes[3].name) { + WaterFlowDynamicSwitchover(); + } +} + +@Entry +@Component +struct WaterFlowExample { + @Consume pathStack: NavPathStack; + + build() { + NavDestination() { + List({ space: 12 }) { + ForEach(routes, (route: Route) => { + ListItem() { + CompletedRoutableCard({ title: route.title, description: route.description }) + } + .width('100%') + .onClick(() => { + this.pathStack.pushPath({ name: route.name }); + }) + }) + } + .contentStartOffset(56) + .padding({ left: 16, right: 16 }) + } + .backgroundColor('#f1f3f5') + .title('WaterFlow', { + backgroundBlurStyle: BlurStyle.COMPONENT_THICK, + barStyle: BarStyle.STACK + }) + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(0).JPG b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(0).JPG new file mode 100644 index 0000000000000000000000000000000000000000..fc503bbffd260e135a6d1b8050ae8270b5b7b334 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(0).JPG differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(1).JPG b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(1).JPG new file mode 100644 index 0000000000000000000000000000000000000000..1085f839befca033a2687c554a47d535d589dc59 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(1).JPG differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(2).JPG b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(2).JPG new file mode 100644 index 0000000000000000000000000000000000000000..680348896f729a6b7d3860613403485a5a3090b7 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(2).JPG differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(3).JPG b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(3).JPG new file mode 100644 index 0000000000000000000000000000000000000000..0805dade041dc79b2dbc336f104fbaa8c86186e7 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(3).JPG differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(4).JPG b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(4).JPG new file mode 100644 index 0000000000000000000000000000000000000000..1ee3676323ab5637c00f5d486e72f5d6776e85a7 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(4).JPG differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(5).JPG b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(5).JPG new file mode 100644 index 0000000000000000000000000000000000000000..f1488adf937caeaf3b70a6d43d5fb228e15e1d37 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/ets/res/waterFlow(5).JPG differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/module.json5 b/ArkUIKit/ScrollableComponent/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4144486d1af4c03b0d767cce1cda86fc0d697f91 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/element/color.json b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/element/string.json b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f5f2e04b93c4c18a04876f8e02668d82e6862464 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/element/string.json @@ -0,0 +1,988 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "ScrollableComponent" + }, + { + "name": "pageIndex_List", + "value": "列表/List" + }, + { + "name": "pageIndex_ArcList", + "value": "弧形列表/ArcList" + }, + { + "name": "pageIndex_Grid", + "value": "网格/Grid" + }, + { + "name": "pageIndex_Swiper", + "value": "轮播/Swiper" + }, + { + "name": "pageIndex_ArcSwiper", + "value": "弧形轮播/ArcSwiper" + }, + { + "name": "pageIndex_Tabs", + "value": "选项卡/Tabs" + }, + { + "name": "GridLayout_title", + "value": "网格开发布局" + }, + { + "name": "GridLayout_titleRowSpacing", + "value": "设置行列数量占比和行间距示例" + }, + { + "name": "GridLayout_titleChildSpan", + "value": "设置子组件所占行列数示例" + }, + { + "name": "GridLayout_titleMainAxis", + "value": "设置主轴方向示例" + }, + { + "name": "GridLayout_description", + "value": "示例设置了网格中子组件行列数量占比、行列间距和主轴方向。" + }, + { + "name": "DataInGrid_title", + "value": "网格显示数据" + }, + { + "name": "DataInGrid_titleOfficeServices", + "value": "办公服务网格示例" + }, + { + "name": "DataInGrid_titleForEach", + "value": "办公服务网格ForEach语句示例" + }, + { + "name": "DataInGrid_description", + "value": "示例采用二维布局的方式组织其内部元素,显示通用办公服务网格。" + }, + { + "name": "ScrollableGrid_title", + "value": "可滚动的网格布局" + }, + { + "name": "ScrollableGrid_titleHorizontal", + "value": "横向可滚动网格布局示例" + }, + { + "name": "ScrollableGrid_description", + "value": "示例通过仅设置行、列数量与占比中的一个实现横向可滚动网格布局。" + }, + { + "name": "ScrollPosition_title", + "value": "控制滚动位置的网格布局" + }, + { + "name": "ScrollPosition_titleExample", + "value": "控制滚动位置示例" + }, + { + "name": "ScrollPosition_description", + "value": "示例通过添加Scroller对象的scrollPage方法,实现滚动网格布局翻页滚动的功能。" + }, + { + "name": "SwiperLoop_title", + "value": "循环播放" + }, + { + "name": "SwiperLoop_titleTrue", + "value": "循环播放loop为true的示例" + }, + { + "name": "SwiperLoop_titleFalse", + "value": "循环播放loop为false的示例" + }, + { + "name": "SwiperLoop_description", + "value": "通过设置loop属性控制是否循环播放。" + }, + { + "name": "SwiperAutoPlay_title", + "value": "自动轮播" + }, + { + "name": "SwiperAutoPlay_titleExample", + "value": "自动轮播示例" + }, + { + "name": "SwiperAutoPlay_description", + "value": "通过设置autoPlay属性控制是否自动轮播子组件。" + }, + { + "name": "SwiperIndicatorStyle_title", + "value": "自定义导航点样式" + }, + { + "name": "SwiperIndicatorStyle_titleDefault", + "value": "默认导航点样式示例" + }, + { + "name": "SwiperIndicatorStyle_titleCustom", + "value": "自定义导航点样式示例" + }, + { + "name": "SwiperIndicatorStyle_titleDefaultArrows", + "value": "默认箭头样式导航点样式示例" + }, + { + "name": "SwiperIndicatorStyle_titleCustomArrows", + "value": "自定义箭头样式导航点样式示例" + }, + { + "name": "SwiperIndicatorStyle_description", + "value": "通过indicator属性和displayArrow属性对导航点样式和导航点箭头样式进行设置。" + }, + { + "name": "SwiperPageSwitchMethod_title", + "value": "页面切换方式" + }, + { + "name": "SwiperPageSwitchMethod_titleHorizontal", + "value": "水平方向上轮播示例" + }, + { + "name": "SwiperPageSwitchMethod_titleVertical", + "value": "垂直方向上轮播示例" + }, + { + "name": "SwiperPageSwitchMethod_description", + "value": "Swiper支持手指滑动、点击导航点和通过控制器三种方式切换页面,示例展示通过控制器切换页面的方法。" + }, + { + "name": "SwiperDirection_title", + "value": "轮播方向" + }, + { + "name": "SwiperDirection_description", + "value": "Swiper支持水平和垂直方向上进行轮播,主要通过vertical属性控制。" + }, + { + "name": "SwiperMultiPage_title", + "value": "每页显示多个子页面" + }, + { + "name": "SwiperMultiPage_titleExample", + "value": "每页显示多个子页面示例" + }, + { + "name": "SwiperMultiPage_description", + "value": "Swiper支持在一个页面内同时显示多个子组件,通过displayCount属性设置。" + }, + { + "name": "SwiperCustomAnimation_title", + "value": "自定义切换动画" + }, + { + "name": "SwiperCustomAnimation_titleExample", + "value": "自定义切换动画示例" + }, + { + "name": "SwiperCustomAnimation_description", + "value": "Swiper支持通过customContentTransition设置自定义切换动画。" + }, + { + "name": "TabsLayout_title", + "value": "基本布局" + }, + { + "name": "TabsLayout_titleExample", + "value": "基本布局示例" + }, + { + "name": "TabsLayout_description", + "value": "示例展示Tabs组件页面组成的两个部分,分别是内容页TabContent和导航页签栏TabBar。" + }, + { + "name": "BottomTabBar_title", + "value": "底部导航" + }, + { + "name": "BottomTabBar_titleExample", + "value": "底部导航示例" + }, + { + "name": "homepage", + "value": "首页" + }, + { + "name": "homepage_content", + "value": "首页的内容" + }, + { + "name": "recommend", + "value": "推荐" + }, + { + "name": "recommend_content", + "value": "推荐的内容" + }, + { + "name": "discover", + "value": "发现" + }, + { + "name": "discover_content", + "value": "发现的内容" + }, + { + "name": "mine", + "value": "我的" + }, + { + "name": "mine_content", + "value": "我的内容" + }, + { + "name": "BottomTabBar_description", + "value": "示例展示导航页签栏TabBar在底部的情景。" + }, + { + "name": "TopTabBar_title", + "value": "顶部导航" + }, + { + "name": "TopTabBar_titleExample", + "value": "顶部导航示例" + }, + { + "name": "TopTabBar_description", + "value": "示例展示导航页签栏TabBar在顶部的情景。" + }, + { + "name": "SideTabBar_title", + "value": "侧边导航" + }, + { + "name": "SideTabBar_titleExample", + "value": "侧边导航示例" + }, + { + "name": "SideTabBar_description", + "value": "示例展示导航页签栏TabBar在侧边的情景。" + }, + { + "name": "SwipeLockedTabBar_title", + "value": "限制导航栏的滑动切换" + }, + { + "name": "SwipeLockedTabBar_titleExample", + "value": "限制导航栏的滑动切换示例" + }, + { + "name": "SwipeLockedTabBar_description", + "value": "示例展示在底部导航+顶部导航组合的情况下,限制底部导航栏滑动的情景。" + }, + { + "name": "FixedTabBar_title", + "value": "固定导航栏" + }, + { + "name": "FixedTabBar_titleExample", + "value": "固定导航栏示例" + }, + { + "name": "FixedTabBar_description", + "value": "示例展示底部导航内容分类一般固定,分类数量一般在3-5个,使用固定导航栏的情景。" + }, + { + "name": "ScrollableTabBar_title", + "value": "滚动导航栏" + }, + { + "name": "ScrollableTabBar_titleExample", + "value": "滚动导航栏示例" + }, + { + "name": "FocusOn_content", + "value": "关注的内容" + }, + { + "name": "game_content", + "value": "游戏的内容" + }, + { + "name": "digit_content", + "value": "数码的内容" + }, + { + "name": "technology_content", + "value": "科技的内容" + }, + { + "name": "sport_content", + "value": "体育的内容" + }, + { + "name": "film_content", + "value": "影视的内容" + }, + { + "name": "humanities_content", + "value": "人文的内容" + }, + { + "name": "FocusOn", + "value": "关注" + }, + { + "name": "game", + "value": "游戏" + }, + { + "name": "digit", + "value": "数码" + }, + { + "name": "technology", + "value": "科技" + }, + { + "name": "sport", + "value": "体育" + }, + { + "name": "film", + "value": "影视" + }, + { + "name": "humanities", + "value": "人文" + }, + { + "name": "ScrollableTabBar_description", + "value": "示例展示内容分类较多,屏幕宽度无法容纳所有分类页签的情况下,需要使用可滚动的导航栏的情景。" + }, + { + "name": "CustomTabBar_title", + "value": "自定义导航栏" + }, + { + "name": "CustomTabBar_titleExample", + "value": "自定义导航栏示例" + }, + { + "name": "internet_content", + "value": "网络的内容" + }, + { + "name": "album_content", + "value": "相册的内容" + }, + { + "name": "video_content", + "value": "视频的内容" + }, + { + "name": "more_content", + "value": "更多的内容" + }, + { + "name": "internet", + "value": "网络" + }, + { + "name": "album", + "value": "相册" + }, + { + "name": "video", + "value": "视频" + }, + { + "name": "more", + "value": "更多" + }, + { + "name": "CustomTabBar_description", + "value": "示例展示通过组合文字以及对应语义图标表示页签内容,自定义导航栏样式的情景。" + }, + { + "name": "ContentWillChange_title", + "value": "切换至指定页签" + }, + { + "name": "ContentWillChange_titleContentAndTabSync", + "value": "内容页和页签联动示例" + }, + { + "name": "ContentWillChange_titleSpecifiedTab", + "value": "切换指定页签示例" + }, + { + "name": "ContentWillChange_titleInterception", + "value": "支持开发者自定义页面切换拦截事件示例" + }, + { + "name": "ContentWillChange_changeIndex", + "value": "动态修改index" + }, + { + "name": "ContentWillChange_description", + "value": "示例展示使用了自定义导航栏后,自行实现页签切换逻辑。" + }, + { + "name": "AgeFriendlyTabs_title", + "value": "支持适老化" + }, + { + "name": "AgeFriendlyTabs_description", + "value": "示例展示在适老化大字体场景下,底部页签提供大字体弹窗显示内容。" + }, + { + "name": "ListLayout_title", + "value": "列表开发布局" + }, + { + "name": "ListLayout_titleMainAxis", + "value": "设置主轴方向布局" + }, + { + "name": "ListLayout_titleCrossAxisLanes", + "value": "设置交叉轴布局lanes属性" + }, + { + "name": "ListLayout_titleCrossAxisAlignment", + "value": "设置交叉轴布局alignListItem属性" + }, + { + "name": "ListLayout_description", + "value": "展示列表主轴和交叉轴布局的各种示例。" + }, + { + "name": "DataInList_title", + "value": "列表显示数据" + }, + { + "name": "DataInList_titlePage", + "value": "在列表中显示数据" + }, + { + "name": "DataInList_titleCityList", + "value": "城市列表示例" + }, + { + "name": "city_beijing", + "value": "北京" + }, + { + "name": "city_hangzhou", + "value": "杭州" + }, + { + "name": "city_shanghai", + "value": "上海" + }, + { + "name": "peopleOne", + "value": "小明" + }, + { + "name": "peopleTwo", + "value": "小红" + }, + { + "name": "DataInList_titleContactsList", + "value": "联系人列表示例" + }, + { + "name": "DataInList_description", + "value": "示例模拟显示城市列表,以及图片和文字一起显示的联系人列表。" + }, + { + "name": "ListIteration_title", + "value": "迭代列表内容" + }, + { + "name": "ListIteration_titleExample", + "value": "迭代列表内容示例" + }, + { + "name": "ListIteration_description", + "value": "示例通过数据集合动态地创建列表。" + }, + { + "name": "CustomListStyle_title", + "value": "自定义列表样式" + }, + { + "name": "CustomListStyle_titleContentSpacing", + "value": "设置内容间距" + }, + { + "name": "CustomListStyle_titleDividerLines", + "value": "添加分隔线" + }, + { + "name": "CustomListStyle_titleScrollbars", + "value": "添加滚动条" + }, + { + "name": "CustomListStyle_description", + "value": "示例通过属性自定义设置列表的内容间距、分隔线、滚动条等样式。" + }, + { + "name": "GroupedList_title", + "value": "支持分组列表" + }, + { + "name": "GroupedList_titleExample", + "value": "支持分组列表示例" + }, + { + "name": "GroupedList_description", + "value": "示例在列表中支持数据分组展示,可以使列表显示结构清晰,查找方便,从而提高使用效率。" + }, + { + "name": "StickyHeaderList_title", + "value": "添加粘性标题" + }, + { + "name": "StickyHeaderList_titleExample", + "value": "添加粘性标题示例" + }, + { + "name": "StickyHeaderList_description", + "value": "粘性标题常用于定位字母列表的头部元素,有助于阐明列表中数据的表示形式和用途,帮助用户进行数据定位。" + }, + { + "name": "ControlledScrollPositionList_title", + "value": "控制滚动位置" + }, + { + "name": "ControlledScrollPositionList_titleExample", + "value": "控制滚动位置示例" + }, + { + "name": "ControlledScrollPositionList_description", + "value": "当列表中新闻页列表项数量庞大时,可以快速滚动到列表底部或返回列表顶部。" + }, + { + "name": "ResponsiveScrollPositionList_title", + "value": "响应滚动位置" + }, + { + "name": "ResponsiveScrollPositionList_titleExample", + "value": "响应滚动位置示例" + }, + { + "name": "contacts_A_one", + "value": "艾佳" + }, + { + "name": "contacts_A_two", + "value": "安安" + }, + { + "name": "contacts_B_one", + "value": "白叶" + }, + { + "name": "contacts_B_two", + "value": "伯伯" + }, + { + "name": "contacts_B_three", + "value": "伯明" + }, + { + "name": "contacts_D_one", + "value": "大白" + }, + { + "name": "contacts_D_two", + "value": "大伯" + }, + { + "name": "contacts_D_three", + "value": "大明" + }, + { + "name": "contacts_F_one", + "value": "帆帆" + }, + { + "name": "contacts_F_two", + "value": "芳芳" + }, + { + "name": "contacts_G_one", + "value": "刚刚" + }, + { + "name": "contacts_G_two", + "value": "哥哥" + }, + { + "name": "contacts_H_one", + "value": "花花" + }, + { + "name": "contacts_H_two", + "value": "华华" + }, + { + "name": "contacts_H_three", + "value": "欢欢" + }, + { + "name": "contacts_X_one", + "value": "小李" + }, + { + "name": "contacts_X_two", + "value": "小王" + }, + { + "name": "contacts_X_three", + "value": "小张" + }, + { + "name": "ResponsiveScrollPositionList_description", + "value": "在联系人列表滚动时,如果跨越了不同字母开头的分组,则侧边字母索引栏也需要更新到对应的字母位置。" + }, + { + "name": "SwipeListItem_title", + "value": "响应列表项侧滑" + }, + { + "name": "SwipeListItem_titleExample", + "value": "响应列表项侧滑示例" + }, + { + "name": "SwipeListItem_description", + "value": "在消息列表中,给消息列表提供侧滑删除功能。" + }, + { + "name": "TaggedListItems_title", + "value": "给列表项添加标记" + }, + { + "name": "TaggedListItems_titleExample", + "value": "给列表项添加标记示例" + }, + { + "name": "TaggedListItems_description", + "value": "在消息列表中,给消息信息右上角添加标记。" + }, + { + "name": "AddListItem_title", + "value": "新增列表项" + }, + { + "name": "AddListItem_titleExample", + "value": "新增列表项示例" + }, + { + "name": "TodoItem", + "value": "待办" + }, + { + "name": "AddListItem_description", + "value": "在示例中击添加按钮,列表项内容选择或填写的交互界面,用户点击确定后,列表中新增对应的项目。" + }, + { + "name": "DeleteListItem_title", + "value": "删除列表项" + }, + { + "name": "DeleteListItem_titleExample", + "value": "删除列表项示例" + }, + { + "name": "DeleteListItem_description", + "value": "在示例中用户长按列表项进入删除模式,提供用户删除列表项选择的交互界面,勾选完成后点击删除按钮,列表中删除对应的项目。" + }, + { + "name": "pageIndex_WaterFlow", + "value": "创建瀑布流/WaterFlow" + }, + { + "name": "WaterFlowInfiniteScrolling_title", + "value": "无限滚动(到达末尾时新增数据)" + }, + { + "name": "WaterFlowInfiniteScrolling_description", + "value": "在瀑布流组件到达末尾位置时触发事件回调,增加新数据。" + }, + { + "name": "WaterFlowInfiniteScrollingEarly_title", + "value": "无限滚动(提前新增数据)" + }, + { + "name": "WaterFlowInfiniteScrollingEarly_description", + "value": "为了实现更加流畅的无限滑动,需要调整增加新数据的时机。可以在还剩余若干个数据未遍历的情况下提前加载新数据。" + }, + { + "name": "WaterFlowGroupingMixing_title", + "value": "分组混合布局" + }, + { + "name": "WaterFlowGroupingMixing_description", + "value": "许多应用界面在瀑布流上方包含其他内容,这类场景可通过在Scroll或List内部嵌套WaterFlow来实现。" + }, + { + "name": "WaterFlowDynamicSwitchover_title", + "value": "动态切换列数" + }, + { + "name": "WaterFlowDynamicSwitchover_description", + "value": "通过动态调整瀑布流的列数,应用能够实现在列表模式与瀑布流模式间的切换,或适应屏幕宽度的变化。" + }, + { + "name": "GridSideToSide_title", + "value": "控制滚动位置" + }, + { + "name": "GridSideToSide_description", + "value": "与新闻列表的返回顶部场景类似,控制滚动位置功能在网格布局中也很常用,例如下图所示日历的翻页功能。" + }, + { + "name": "GridScrollbar_title", + "value": "添加外置滚动条" + }, + { + "name": "GridScrollbar_description", + "value": "网格组件Grid可与ScrollBar组件配合使用,为网格添加外置滚动条。" + }, + { + "name": "ArcSwiperHorizontal_title", + "value": "水平方向轮播" + }, + { + "name": "ArcSwiperHorizontal_description", + "value": "设置水平方向上轮播。" + }, + { + "name": "ArcSwiperVertical_title", + "value": "垂直方向轮播" + }, + { + "name": "ArcSwiperVertical_description", + "value": "设置垂直方向轮播,导航点设为3点钟方向。。" + }, + { + "name": "ArcSwiperAction_title", + "value": "自定义切换动画" + }, + { + "name": "ArcSwiperAction_description", + "value": "ArcSwiper支持设置自定义切换动画,可以在回调中对视窗内所有页面逐帧设置透明度、缩放比例、位移、渲染层级等属性,从而实现自定义切换动画效果。" + }, + { + "name": "ArcSwiperSideSlip_title", + "value": "实现侧滑返回" + }, + { + "name": "ArcSwiperSideSlip_description", + "value": "ArcSwiper的滑动事件会与侧滑返回冲突,可以通过手势拦截去判断ArcSwiper是否滑动到开头去拦截ArcSwiper的滑动手势,实现再次左滑返回上一页的功能。" + }, + { + "name": "ArcSwiperStyles_title", + "value": "设置导航点样式" + }, + { + "name": "ArcSwiperStyles_titleDefault", + "value": "导航点使用默认样式" + }, + { + "name": "ArcSwiperStyles_titleCustomize", + "value": "自定义导航点样式" + }, + { + "name": "ArcSwiperStyles_description", + "value": "ArcSwiper提供了默认的弧形导航点样式,导航点默认显示在ArcSwiper下方居中位置,开发者也可以通过indicator属性自定义弧形导航点的样式。" + }, + { + "name": "ArcSwiperToggle_title", + "value": "控制页面切换方式" + }, + { + "name": "ArcSwiperToggle_description", + "value": "以下示例展示通过控制控制器和旋转表冠翻页的方法。" + }, + { + "name": "ArcListAcrScrollBar_title", + "value": "添加外置滚动条ArcScrollBar" + }, + { + "name": "ArcListAcrScrollBar_description", + "value": "弧形列表ArcList可与ArcScrollBar组件配合使用,为弧形列表添加外置滚动条。" + }, + { + "name": "ArcListArcIndexerBar_title", + "value": "与弧形索引条ArcAlphabetIndexer联动" + }, + { + "name": "ArcListArcIndexerBar_description", + "value": "许多应用需要监测列表的滚动位置变动并作出响应,或通过调整滚动位置实现列表的快速定位。为此,需使用弧形索引条组件ArcAlphabetIndexer。" + }, + { + "name": "arcListBuiltInScrollerBar_title", + "value": "添加内置滚动条" + }, + { + "name": "arcListBuiltInScrollerBar_description", + "value": "当列表项的高度超过屏幕高度时,弧形列表能够沿垂直方向滚动。" + }, + { + "name": "ArcListContents_title", + "value": "迭代弧形列表内容" + }, + { + "name": "ArcListContents_description", + "value": "通常,应用会通过数据集合动态创建列表。采用循环渲染的方式,可以从数据源中迭代获取数据,在每次迭代过程中创建相应的组件,从而降低代码的复杂度。" + }, + { + "name": "ArcListCrown_title", + "value": "响应旋转表冠" + }, + { + "name": "ArcListCrown_description", + "value": "手表设备上弧形列表在获焦的情况下可对旋转表冠做出响应,用户可通过旋转表冠的操作滑动列表,浏览列表项数据。" + }, + { + "name": "ArcListShow_title", + "value": "在弧形列表中显示数据" + }, + { + "name": "ArcListShow_description", + "value": "弧形列表视图垂直展示项目集合,当列表项超出屏幕范围时,提供滚动功能,这使得它非常适合展示大型数据集合。" + }, + { + "name": "ArcListSideSlip_title", + "value": "响应列表项侧滑" + }, + { + "name": "ArcListSideSlip_description", + "value": "ArcListItem的swipeAction属性可用于实现列表项的左右滑动功能。" + }, + { + "name": "ArcListStyles_head", + "value": "自定义弧形列表标题" + }, + { + "name": "ArcListStyles_title", + "value": "自定义弧形列表样式" + }, + { + "name": "ArcListStyles_titleSpacing", + "value": "自定义弧形列表项间距" + }, + { + "name": "ArcListStyles_titleScale", + "value": "列表项关闭自动缩放" + }, + { + "name": "ArcListStyles_description", + "value": "以下示例展示自定义弧形列表样式的方法。" + }, + { + "name": "LongList_title", + "value": "长列表的处理" + }, + { + "name": "LongList_description", + "value": "循环渲染适用于短列表,当构建具有大量列表项的长列表时,如果直接采用循环渲染方式,会一次性加载所有的列表元素,会导致页面启动时间过长,影响用户体验。因此,推荐使用数据懒加载(LazyForEach)方式实现按需迭代加载数据,从而提升列表性能。" + }, + { + "name": "CollapseAndExpand_title", + "value": "折叠与展开" + }, + { + "name": "CollapseAndExpand_description", + "value": "列表项的折叠与展开用途广泛,常用于信息清单的展示、填写等应用场景。" + }, + { + "name": "SwiperAndTabsLinkage_title", + "value": "Swiper与Tabs联动" + }, + { + "name": "SwiperAndTabsLinkage_description", + "value": "Swiper选中的元素改变时,会通过onSelected回调事件,将元素的索引值index返回。通过调用tabsController.changeIndex(index)方法来实现Tabs页签的切换。" + }, + { + "name": "SwiperIgnoreComponentSize_title", + "value": "设置圆点导航点间距和忽略导航点组件大小" + }, + { + "name": "SwiperIgnoreComponentSize_description", + "value": "针对圆点导航点,可以通过DotIndicator的space属性来设置圆点导航点的间距。当导航点的bottom设为0之后,导航点的底部与Swiper的底部还会有一定间距。如果希望消除该间距,可通过调用bottom(bottom, ignoreSize)属性来进行设置。" + }, + { + "name": "ArcLongList_title", + "value": "处理长列表" + }, + { + "name": "ArcLongList_description", + "value": "循环渲染适用于短列表,当构建具有大量列表项的长列表时,如果直接采用循环渲染方式,会一次性加载所有的列表元素,会导致页面启动时间过长,影响用户体验。因此,推荐使用数据懒加载(LazyForEach)方式实现按需迭代加载数据,从而提升列表性能。" + }, + { + "name": "ListChatRoom_title", + "value": "切换布局方向" + }, + { + "name": "ListChatRoom_description", + "value": "部分业务场景需要列表底部插入数据时,自动向上滚动,把新插入的节点展示出来。" + }, + { + "name": "LongGrid_title", + "value": "性能优化" + }, + { + "name": "LongGrid_description", + "value": "与长列表的处理类似,循环渲染适用于数据量较小的布局场景,当构建具有大量网格项的可滚动网格布局时,推荐使用数据懒加载方式实现按需迭代加载数据,从而提升列表性能。" + }, + { + "name": "GridCalculator_title", + "value": "计算器的按键布局" + }, + { + "name": "GridCalculator_description", + "value": "实现不同大小的网格组成不均匀分布的网格布局场景" + }, + { + "name": "ArcListCrown_set", + "value": "设置" + }, + { + "name": "ArcListStyles_waln", + "value": "WLAN" + }, + { + "name": "ArcListStyles_open", + "value": "已开启" + }, + { + "name": "ArcListStyles_blue", + "value": "蓝牙" + }, + { + "name": "ArcListStyles_net", + "value": "移动网络" + }, + { + "name": "ArcListStyles_connect", + "value": "更多连接" + }, + { + "name": "ArcListStyles_light", + "value": "显示和亮度" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/MaterialSymbolsDelete.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/MaterialSymbolsDelete.svg new file mode 100644 index 0000000000000000000000000000000000000000..8f8348613dafc3fb1a1adbaa0f978bd3e9398fd7 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/MaterialSymbolsDelete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/background.png b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/background.png differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/blueTooth.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/blueTooth.svg new file mode 100644 index 0000000000000000000000000000000000000000..0fbcf2bd2720f8bc33ce34552ff07b0238523088 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/blueTooth.svg @@ -0,0 +1,16 @@ + + + 编组 + + + + + + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/delete.png b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..1714478bde5bd46fa9856e0ebc06be459c4664f2 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/delete.png differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/displayAndBrightness.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/displayAndBrightness.svg new file mode 100644 index 0000000000000000000000000000000000000000..c19e018d71201ed17e239da5851bde5a9cfaf12a --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/displayAndBrightness.svg @@ -0,0 +1,16 @@ + + + 编组 + + + + + + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/foreground.png b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/foreground.png differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_contact.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_contact.svg new file mode 100644 index 0000000000000000000000000000000000000000..45128f1a45c7f70b96217f8a840eb6ca922f5e56 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_contact.svg @@ -0,0 +1,21 @@ + + + 默认头像icon + + + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_arrow.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_arrow.svg new file mode 100644 index 0000000000000000000000000000000000000000..ff6293ce432d79ed6c50d61d430ee79fe2e2dad2 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_arrow.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_more_connections.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_more_connections.svg new file mode 100644 index 0000000000000000000000000000000000000000..7e654cf2401d3f4c5db1c971fcefb28af119ef2a --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_more_connections.svg @@ -0,0 +1,21 @@ + + + 更多连接 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_wifi.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_wifi.svg new file mode 100644 index 0000000000000000000000000000000000000000..53dadba1d2dac8ca8b98697705edb004874404c5 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_wifi.svg @@ -0,0 +1,11 @@ + + + Artboard + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/layered_image.json b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/mobileData.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/mobileData.svg new file mode 100644 index 0000000000000000000000000000000000000000..3af781748dbcef004e85fc31d92da3175b21c6c1 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/mobileData.svg @@ -0,0 +1,19 @@ + + + 编组 10 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/startIcon.png b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/wlan.svg b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/wlan.svg new file mode 100644 index 0000000000000000000000000000000000000000..be12071bad8d8780bf172fb777cc7bf5c76e5a57 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/media/wlan.svg @@ -0,0 +1,16 @@ + + + 编组 17 + + + + + + + + + + + + + \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/profile/backup_config.json b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ArkUIKit/ScrollableComponent/entry/src/main/resources/dark/element/color.json b/ArkUIKit/ScrollableComponent/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/mock/mock-config.json5 b/ArkUIKit/ScrollableComponent/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/Ability.test.ets b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/List.test.ets b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c16bc08c6fb53175fcdc9d628a4d6a9b34bef4c --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; +import IndexTest from './index.test'; + +export default function testsuite() { + abilityTest(); + IndexTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..30b111830deafd1cbbb852db21fa483d02371daa --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets @@ -0,0 +1,1324 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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,MatchPattern, UiDirection } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { Point } from '@ohos.UiTest'; + + +const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let want: Want; + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let textString: string = await manage.getStringValue(resource); + return textString; +} + +export default function IndexTest() { + describe('IndexTest', () => { + beforeAll(async () => { + 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 testControlledScrollPositionList + * @tc.desc 测试控制滚动位置示例 + */ + it('testControlledScrollPositionList', 0, async (done: Function) => { + console.info('uitest: testControlledScrollPositionList begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ControlledScrollPositionList_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let stackList = await driver.findComponent(ON.type('Stack')); + expect(stackList === null).assertFalse(); + let button = await driver.findComponent(ON.type('Button')); + expect(button === null).assertFalse(); + await stackList.scrollToBottom(2400); + await button.click(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testControlledScrollPositionList end'); + done(); + }) + + /** + * @tc.number UiTest_002 + * @tc.name testResponsiveScrollPositionList + * @tc.desc 测试响应滚动位置示例 + */ + it('testResponsiveScrollPositionList', 0, async (done: Function) => { + console.info('uitest: testResponsiveScrollPositionList begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ResponsiveScrollPositionList_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let stackList = await driver.findComponent(ON.type('Stack')); + expect(stackList === null).assertFalse(); + await stackList.scrollToBottom(2400); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testResponsiveScrollPositionList end'); + done(); + }) + + /** + * @tc.number UiTest_003 + * @tc.name testDataInList + * @tc.desc 测试列表显示数据示例 + */ + it('testDataInList', 0, async (done: Function) => { + console.info('uitest: testDataInList begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.DataInList_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + str = await getResourceString($r('app.string.peopleOne')); + let dataListText = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(dataListText === null).assertFalse(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testDataInList end'); + done(); + }) + + /** + * @tc.number UiTest_004 + * @tc.name testStickyHeaderList + * @tc.desc 测试添加粘性标题示例 + */ + it('testStickyHeaderList', 0, async (done: Function) => { + console.info('uitest: testStickyHeaderList begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.StickyHeaderList_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let stickyList = await driver.findComponent(ON.type('List')); + expect(stickyList === null).assertFalse(); + await stickyList.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testStickyHeaderList end'); + done(); + }) + + /** + * @tc.number UiTest_005 + * @tc.name testAddListItem + * @tc.desc 测试新增列表项示例 + */ + it('testAddListItem', 0, async (done: Function) => { + console.info('uitest: testAddListItem begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,17); + let str = await getResourceString($r('app.string.AddListItem_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let addButton = await driver.findComponent(ON.text('+', MatchPattern.CONTAINS)); + expect(addButton === null).assertFalse(); + await addButton.click(); + await driver.mouseClick({x: 580, y: 770}, MouseButton.MOUSE_BUTTON_LEFT, 0, 0); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testAddListItem end'); + done(); + }) + + /** + * @tc.number UiTest_006 + * @tc.name testDeleteListItem + * @tc.desc 测试删除列表项示例 + */ + it('testDeleteListItem', 0, async (done: Function) => { + console.info('uitest: testDeleteListItem begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,17); + let str = await getResourceString($r('app.string.DeleteListItem_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let addButton = await driver.findComponent(ON.text('+', MatchPattern.CONTAINS)); + expect(addButton === null).assertFalse(); + await addButton.click(); + await driver.mouseClick({x: 580, y: 770}, MouseButton.MOUSE_BUTTON_LEFT, 0, 0); + let listContent = await driver.findComponent(ON.text('Reading', MatchPattern.CONTAINS)); + expect(listContent === null).assertFalse(); + await listContent.longClick(); + let deleteButton = await driver.findComponent(ON.text('delete', MatchPattern.CONTAINS)); + expect(deleteButton === null).assertFalse(); + await deleteButton.click(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testDeleteListItem end'); + done(); + }) + + /** + * @tc.number UiTest_007 + * @tc.name testListLayout + * @tc.desc 测试列表开发布局示例 + */ + it('testListLayout', 0, async (done: Function) => { + console.info('uitest: testListLayout begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ListLayout_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let dataListText = await driver.findComponent(ON.text('ListItem one', MatchPattern.CONTAINS)); + expect(dataListText === null).assertFalse(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testListLayout end'); + done(); + }) + + /** + * @tc.number UiTest_008 + * @tc.name testGridScrollPosition + * @tc.desc 测试控制滚动位置的网格布局示例 + */ + it('testGridScrollPosition', 0, async (done: Function) => { + console.info('uitest: testGridScrollPosition begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Grid', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ScrollPosition_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let buttonPrevious = await driver.findComponent(ON.text('Previous', MatchPattern.CONTAINS)); + let buttonNext = await driver.findComponent(ON.text('Next', MatchPattern.CONTAINS)); + expect(buttonPrevious === null).assertFalse(); + expect(buttonNext === null).assertFalse(); + await buttonNext.click(); + await buttonPrevious.click(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testGridScrollPosition end'); + done(); + }) + + /** + * @tc.number UiTest_009 + * @tc.name testGridScrollableGrid + * @tc.desc 测试可滚动的网格布局示例 + */ + it('testGridScrollableGrid', 0, async (done: Function) => { + console.info('uitest: testGridScrollableGrid begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Grid', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ScrollableGrid_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let scrollableGrid = await driver.findComponent(ON.type('Grid')); + expect(scrollableGrid === null).assertFalse(); + await scrollableGrid.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testGridScrollableGrid end'); + done(); + }) + + /** + * @tc.number UiTest_010 + * @tc.name testSwiperAutoPlay + * @tc.desc 测试自动轮播示例 + */ + it('testSwiperAutoPlay', 0, async (done: Function) => { + console.info('uitest: testSwiperAutoPlay begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Swiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwiperAutoPlay_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwiperAutoPlay end'); + done(); + }) + + /** + * @tc.number UiTest_011 + * @tc.name testSwiperDirection + * @tc.desc 测试轮播方向示例 + */ + it('testSwiperDirection', 0, async (done: Function) => { + console.info('uitest: testSwiperCustomAnimation begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Swiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwiperDirection_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + let scrollPoint2:Point = {x:400,y:800}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.mouseScroll(scrollPoint2,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwiperCustomAnimation end'); + done(); + }) + + /** + * @tc.number UiTest_012 + * @tc.name testSwiperMultiPage + * @tc.desc 测试每页显示多个子页面示例 + */ + it('testSwiperMultiPage', 0, async (done: Function) => { + console.info('uitest: testSwiperMultiPage begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Swiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwiperMultiPage_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwiperMultiPage end'); + done(); + }) + + /** + * @tc.number UiTest_013 + * @tc.name testSwiperCustomAnimation + * @tc.desc 测试自定义切换动画示例 + */ + it('testSwiperCustomAnimation', 0, async (done: Function) => { + console.info('uitest: testSwiperCustomAnimation begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Swiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwiperCustomAnimation_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwiperCustomAnimation end'); + done(); + }) + + /** + * @tc.number UiTest_014 + * @tc.name testSwiperPageSwitchMethod + * @tc.desc 测试页面切换方式示例 + */ + it('testSwiperPageSwitchMethod', 0, async (done: Function) => { + console.info('uitest: testSwiperPageSwitchMethod begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Swiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwiperPageSwitchMethod_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let buttonPrevious = await driver.findComponent(ON.text('showPrevious', MatchPattern.CONTAINS)); + let buttonNext = await driver.findComponent(ON.text('showNext', MatchPattern.CONTAINS)); + expect(buttonPrevious === null).assertFalse(); + expect(buttonNext === null).assertFalse(); + await buttonNext.click(); + await buttonPrevious.click(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwiperPageSwitchMethod end'); + done(); + }) + + /** + * @tc.number UiTest_015 + * @tc.name testTabsLayout + * @tc.desc 测试基本布局示例 + */ + it('testTabsLayout', 0, async (done: Function) => { + console.info('uitest: testTabsLayout begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.TabsLayout_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testTabsLayout end'); + done(); + }) + + /** + * @tc.number UiTest_016 + * @tc.name testBottomTabBar + * @tc.desc 测试底部导航示例 + */ + it('testBottomTabBar', 0, async (done: Function) => { + console.info('uitest: testBottomTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.BottomTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testBottomTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_017 + * @tc.name testTopTabBar + * @tc.desc 测试顶部导航示例 + */ + it('testTopTabBar', 0, async (done: Function) => { + console.info('uitest: testBottomTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.TopTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testBottomTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_018 + * @tc.name testSideTabBar + * @tc.desc 测试侧边导航示例 + */ + it('testSideTabBar', 0, async (done: Function) => { + console.info('uitest: tesSideTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SideTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,4); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: tesSideTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_019 + * @tc.name testSwipeLockedTabBar + * @tc.desc 测试限制导航栏的滑动切换示例 + */ + it('testSwipeLockedTabBar', 0, async (done: Function) => { + console.info('uitest: testSwipeLockedTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwipeLockedTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,4); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwipeLockedTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_020 + * @tc.name testFixedTabBar + * @tc.desc 测试固定导航栏示例 + */ + it('testFixedTabBar', 0, async (done: Function) => { + console.info('uitest: testFixedTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.FixedTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,4); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testFixedTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_021 + * @tc.name testScrollableTabBar + * @tc.desc 测试滚动导航栏示例 + */ + it('testScrollableTabBar', 0, async (done: Function) => { + console.info('uitest: testScrollableTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ScrollableTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,12); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testScrollableTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_022 + * @tc.name testCustomTabBar + * @tc.desc 测试自定义导航栏示例 + */ + it('testCustomTabBar', 0, async (done: Function) => { + console.info('uitest: testCustomTabBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Tabs', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.CustomTabBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let tabs = await driver.findComponent(ON.type('Tabs')); + expect(tabs === null).assertFalse(); + let scrollPoint:Point = {x:400,y:400}; + await driver.mouseScroll(scrollPoint,true,4); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testCustomTabBar end'); + done(); + }) + + /** + * @tc.number UiTest_023 + * @tc.name testArcSwiperAction + * @tc.desc 测试弧形轮播动画示例 + */ + it('ArcSwiperAction', 0, async (done: Function) => { + console.info('uitest: testSwiperCustomAnimation begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcSwiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcSwiperAction_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:300,y:300}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcSwiperAction end'); + done(); + }) + + /** + * @tc.number UiTest_024 + * @tc.name testArcSwiperVertical + * @tc.desc 测试弧形轮播垂直方向示例 + */ + it('ArcSwiperVertical ', 0, async (done: Function) => { + console.info('uitest: testArcSwiperVertical begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcSwiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcSwiperVertical_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:300,y:300}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcSwiperVertical end'); + done(); + }) + + /** + * @tc.number UiTest_025 + * @tc.name testArcSwiperHorizontal + * @tc.desc 测试弧形轮播水平方向示例 + */ + it('ArcSwiperHorizontal', 0, async (done: Function) => { + console.info('uitest: testArcSwiperHorizontal begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcSwiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcSwiperHorizontal_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:300,y:300}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcSwiperHorizontal end'); + done(); + }) + + /** + * @tc.number UiTest_026 + * @tc.name testArcSwiperSideSlip + * @tc.desc 测试弧形轮播侧滑返回示例 + */ + it('ArcSwiperSideSlip', 0, async (done: Function) => { + console.info('uitest: testArcSwiperSideSlip begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcSwiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcSwiperSideSlip_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:300,y:300}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.mouseScroll(scrollPoint,false,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcSwiperSideSlip end'); + done(); + }) + + /** + * @tc.number UiTest_027 + * @tc.name testArcSwiperToggle + * @tc.desc 测试弧形轮播页面切换方式示例 + */ + it('ArcSwiperToggle', 0, async (done: Function) => { + console.info('uitest: testArcSwiperToggle begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcSwiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcSwiperToggle_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let preArcButton = await driver.findComponent(ON.text('previous', MatchPattern.CONTAINS)); + let nextArcButton = await driver.findComponent(ON.text('next', MatchPattern.CONTAINS)); + expect(preArcButton === null).assertFalse(); + expect(nextArcButton === null).assertFalse(); + await nextArcButton.click(); + await preArcButton.click(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcSwiperToggle end'); + done(); + }) + + /** + * @tc.number UiTest_028 + * @tc.name testArcSwiperStyles + * @tc.desc 测试弧形轮播设置导航点样式示例 + */ + it('ArcSwiperStyles', 0, async (done: Function) => { + console.info('uitest: testArcSwiperToggle begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcSwiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcSwiperStyles_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:300,y:300}; + let scrollPoint2:Point = {x:300,y:600}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.mouseScroll(scrollPoint2,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcSwiperStyles end'); + done(); + }) + + /** + * @tc.number UiTest_029 + * @tc.name testSwiperAndTabsLinkage + * @tc.desc 测试轮播与选项卡联动示例 + */ + it('SwiperAndTabsLinkage', 0, async (done: Function) => { + console.info('uitest: testSwiperAndTabsLinkage begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Swiper', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.SwiperAndTabsLinkage_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let swiper = await driver.findComponent(ON.type('Swiper')); + expect(swiper === null).assertFalse(); + let scrollPoint:Point = {x:400,y:500}; + await driver.mouseScroll(scrollPoint,true,2); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testSwiperAndTabsLinkage end'); + done(); + }) + + /** + * @tc.number UiTest_030 + * @tc.name testLongGrid + * @tc.desc 测试网格性能优化示例 + */ + it('LongGrid', 0, async (done: Function) => { + console.info('uitest: testLongGrid begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Grid', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.LongGrid_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let scrollableGrid = await driver.findComponent(ON.type('Grid')); + expect(scrollableGrid === null).assertFalse(); + await scrollableGrid.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testLongGrid end'); + done(); + }) + + /** + * @tc.number UiTest_031 + * @tc.name testGridScrollbar + * @tc.desc 测试网格添加外置滚动条示例 + */ + it('GridScrollbar', 0, async (done: Function) => { + console.info('uitest: testGridScrollbar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Grid', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.GridScrollbar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let scrollableGrid = await driver.findComponent(ON.type('Grid')); + expect(scrollableGrid === null).assertFalse(); + await scrollableGrid.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testGridScrollbar end'); + done(); + }) + + /** + * @tc.number UiTest_032 + * @tc.name testGridSideToSide + * @tc.desc 测试网格控制滚动位置示例 + */ + it('GridSideToSide', 0, async (done: Function) => { + console.info('uitest: testGridSideToSide begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('Grid', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.GridSideToSide_description')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let preArcButton = await driver.findComponent(ON.text('上一页', MatchPattern.CONTAINS)); + let nextArcButton = await driver.findComponent(ON.text('下一页', MatchPattern.CONTAINS)); + expect(preArcButton === null).assertFalse(); + expect(nextArcButton === null).assertFalse(); + await nextArcButton.click(); + await preArcButton.click(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testGridSideToSide end'); + done(); + }) + + /** + * @tc.number UiTest_033 + * @tc.name testLongList + * @tc.desc 测试长列表示例 + */ + it('LongList', 0, async (done: Function) => { + console.info('uitest: testLongList begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let list = await driver.findComponent(ON.type('List')); + expect(list === null).assertFalse(); + await list.scrollToBottom(1000); + let str = await getResourceString($r('app.string.LongList_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let scrollableList = await driver.findComponent(ON.type('List')); + expect(scrollableList === null).assertFalse(); + await scrollableList.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testLongList end'); + done(); + }) + + /** + * @tc.number UiTest_033 + * @tc.name testCollapseAndExpand + * @tc.desc 测试列表折叠与展开示例 + */ + it('CollapseAndExpand', 0, async (done: Function) => { + console.info('uitest: testCollapseAndExpand begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let list = await driver.findComponent(ON.type('List')); + expect(list === null).assertFalse(); + await list.scrollToBottom(1000); + let str = await getResourceString($r('app.string.CollapseAndExpand_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let text = await driver.findComponent(ON.text('个人基本资料', MatchPattern.CONTAINS)); + expect(text === null).assertFalse(); + await text.click(); + let nameText = await driver.findComponent(ON.text('昵称', MatchPattern.CONTAINS)); + expect(nameText === null).assertFalse(); + await text.click(); + nameText = await driver.findComponent(ON.text('昵称', MatchPattern.CONTAINS)); + expect(nameText === null).assertTrue(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testCollapseAndExpand end'); + done(); + }) + + /** + * @tc.number UiTest_035 + * @tc.name testArcLongList + * @tc.desc 测试弧形长列表示例 + */ + it('ArcLongList', 0, async (done: Function) => { + console.info('uitest: testArcLongList begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcLongList_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(15000); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcLongList end'); + done(); + }) + + /** + * @tc.number UiTest_036 + * @tc.name testArcListAcrScrollBar + * @tc.desc 测试弧形列表外置滚动条示例 + */ + it('ArcListAcrScrollBar', 0, async (done: Function) => { + console.info('uitest: testArcListAcrScrollBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcListAcrScrollBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListAcrScrollBar end'); + done(); + }) + + /** + * @tc.number UiTest_037 + * @tc.name testArcListBuiltInScrollerBar + * @tc.desc 测试弧形列表内置滚动条示例 + */ + it('arcListBuiltInScrollerBar', 0, async (done: Function) => { + console.info('uitest: testArcListBuiltInScrollerBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.arcListBuiltInScrollerBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListBuiltInScrollerBar end'); + done(); + }) + + /** + * @tc.number UiTest_038 + * @tc.name testArcListContents + * @tc.desc 测试弧形列表内置滚动条示例 + */ + it('ArcListContents', 0, async (done: Function) => { + console.info('uitest: testArcListContents begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcListContents_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListContents end'); + done(); + }) + + /** + * @tc.number UiTest_039 + * @tc.name testArcListShow + * @tc.desc 测试弧形列表展示数据示例 + */ + it('ArcListShow', 0, async (done: Function) => { + console.info('uitest: testArcListShow begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcListShow_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListShow end'); + done(); + }) + + /** + * @tc.number UiTest_040 + * @tc.name testArcListStyles + * @tc.desc 测试弧形列表设置样式示例 + */ + it('ArcListStyles', 0, async (done: Function) => { + console.info('uitest: testArcListStyles begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcListStyles_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('List')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListStyles end'); + done(); + }) + + /** + * @tc.number UiTest_041 + * @tc.name testArcListArcIndexerBar + * @tc.desc 测试弧形列表联动indexer示例 + */ + it('ArcListArcIndexerBar', 0, async (done: Function) => { + console.info('uitest: testArcListArcIndexerBar begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcListArcIndexerBar_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let button = await driver.findComponent(ON.type('Button')); + expect(button === null).assertFalse(); + await button.click(); + let testText = await driver.findComponent(ON.text('F', MatchPattern.CONTAINS)); + expect(testText === null).assertFalse(); + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + await arclist.scrollToBottom(5000); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListArcIndexerBar end'); + done(); + }) + + /** + * @tc.number UiTest_042 + * @tc.name testArcListSideSlip + * @tc.desc 测试弧形列表侧滑示例 + */ + it('ArcListSideSlip', 0, async (done: Function) => { + console.info('uitest: testArcListSideSlip begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('ArcList', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.ArcListSideSlip_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('ArcList')); + expect(arclist === null).assertFalse(); + let scrollPoint:Point = {x:200,y:500}; + let scrollPoint2:Point = {x:500,y:500}; + + await driver.fling(scrollPoint2,scrollPoint,1,600); + let button = await driver.findComponent(ON.type('Button')); + expect(button === null).assertFalse(); + await button.click(); + let testText = await driver.findComponent(ON.text('Alice', MatchPattern.CONTAINS)); + expect(testText === null).assertTrue(); + await arclist.scrollToBottom(5000); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testArcListSideSlip end'); + done(); + }) + + /** + * @tc.number UiTest_043 + * @tc.name testWaterFlowDynamicSwitchover + * @tc.desc 测试瀑布流动态切换列数示例 + */ + it('WaterFlowDynamicSwitchover', 0, async (done: Function) => { + console.info('uitest: testWaterFlowDynamicSwitchover begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('WaterFlow', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.WaterFlowDynamicSwitchover_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('WaterFlow')); + expect(arclist === null).assertFalse(); + let flowItemText = await driver.findComponent(ON.text('FlowItem0', MatchPattern.CONTAINS)); + expect(flowItemText === null).assertFalse(); + let scrollPoint:Point = {x:350,y:1100}; + let scrollPoint2:Point = {x:350,y:550}; + await driver.fling(scrollPoint,scrollPoint2,1,1200); + let button = await driver.findComponent(ON.type('Button')); + expect(button === null).assertFalse(); + await button.click(); + let testText = await driver.findComponent(ON.text('N9', MatchPattern.CONTAINS)); + expect(testText === null).assertFalse(); + await driver.fling(scrollPoint,scrollPoint2,1,1200); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testWaterFlowDynamicSwitchover end'); + done(); + }) + + /** + * @tc.number UiTest_044 + * @tc.name testWaterFlowGroupingMixing + * @tc.desc 测试瀑布流混合布局示例 + */ + it('WaterFlowGroupingMixing', 0, async (done: Function) => { + console.info('uitest: testWaterFlowGroupingMixing begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('WaterFlow', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.WaterFlowGroupingMixing_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('WaterFlow')); + expect(arclist === null).assertFalse(); + let scrollPoint:Point = {x:350,y:1100}; + let scrollPoint2:Point = {x:350,y:550}; + await driver.fling(scrollPoint,scrollPoint2,1,1200); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testWaterFlowGroupingMixing end'); + done(); + }) + + /** + * @tc.number UiTest_045 + * @tc.name testWaterFlowInfiniteScrolling + * @tc.desc 测试瀑布流无限滑动触底增加示例 + */ + it('WaterFlowInfiniteScrolling', 0, async (done: Function) => { + console.info('uitest: testWaterFlowInfiniteScrolling begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('WaterFlow', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.WaterFlowInfiniteScrolling_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('WaterFlow')); + expect(arclist === null).assertFalse(); + let scrollPoint:Point = {x:350,y:1100}; + let scrollPoint2:Point = {x:350,y:550}; + await driver.fling(scrollPoint,scrollPoint2,1,1200); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testWaterFlowInfiniteScrolling end'); + done(); + }) + + /** + * @tc.number UiTest_046 + * @tc.name testWaterFlowInfiniteScrollingEarly + * @tc.desc 测试瀑布流无限滑动提前增加示例 + */ + it('WaterFlowInfiniteScrollingEarly', 0, async (done: Function) => { + console.info('uitest: testWaterFlowInfiniteScrollingEarly begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('WaterFlow', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let str = await getResourceString($r('app.string.WaterFlowInfiniteScrollingEarly_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let arclist = await driver.findComponent(ON.type('WaterFlow')); + expect(arclist === null).assertFalse(); + let scrollPoint:Point = {x:350,y:1100}; + let scrollPoint2:Point = {x:350,y:550}; + await driver.fling(scrollPoint,scrollPoint2,1,1200); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testWaterFlowInfiniteScrollingEarly end'); + done(); + }) + + /** + * @tc.number UiTest_034 + * @tc.name testListChatRoom + * @tc.desc 测试列表切换布局方向示例 + */ + it('ListChatRoom', 0, async (done: Function) => { + console.info('uitest: testListChatRoom begin'); + let driver = Driver.create(); + let componentButton = await driver.findComponent(ON.text('List', MatchPattern.CONTAINS)); + expect(componentButton === null).assertFalse(); + await componentButton.click(); + let list = await driver.findComponent(ON.type('List')); + expect(list === null).assertFalse(); + await list.scrollToBottom(1000); + let str = await getResourceString($r('app.string.ListChatRoom_title')); + let sampleButton = await driver.findComponent(ON.text(str, MatchPattern.CONTAINS)); + expect(sampleButton === null).assertFalse(); + await sampleButton.click(); + + let textInput = await driver.findComponent(ON.type('TextInput')); + expect(textInput === null).assertFalse(); + await textInput.inputText("message test") + let testButton = await driver.findComponent(ON.text('发送', MatchPattern.CONTAINS)); + expect(testButton === null).assertFalse(); + await testButton.click(); + await driver.mouseClick({x: 670, y: 700}, MouseButton.MOUSE_BUTTON_LEFT, 0, 0); + let nameText = await driver.findComponent(ON.text('message test', MatchPattern.CONTAINS)); + expect(nameText === null).assertFalse(); + await driver.pressBack(); + await driver.pressBack(); + console.info('uitest: testListChatRoom end'); + done(); + }) + + }) +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/ohosTest/module.json5 b/ArkUIKit/ScrollableComponent/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/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/ArkUIKit/ScrollableComponent/entry/src/test/List.test.ets b/ArkUIKit/ScrollableComponent/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/entry/src/test/LocalUnit.test.ets b/ArkUIKit/ScrollableComponent/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ArkUIKit/ScrollableComponent/hvigor/hvigor-config.json5 b/ArkUIKit/ScrollableComponent/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ArkUIKit/ScrollableComponent/hvigorfile.ts b/ArkUIKit/ScrollableComponent/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..2a5e543f190732c159beb574dfc9fa37bc94e156 --- /dev/null +++ b/ArkUIKit/ScrollableComponent/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ArkUIKit/ScrollableComponent/oh-package.json5 b/ArkUIKit/ScrollableComponent/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/ArkUIKit/ScrollableComponent/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ArkUIKit/ScrollableComponent/screenshots/device/image1.png b/ArkUIKit/ScrollableComponent/screenshots/device/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..405d7c9a85730a32a35eb1e90e09dfed55114733 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/screenshots/device/image1.png differ diff --git a/ArkUIKit/ScrollableComponent/screenshots/device/image2.png b/ArkUIKit/ScrollableComponent/screenshots/device/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb783a24ecd950f7ba8e45d4b12d7905cff9e90 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/screenshots/device/image2.png differ diff --git a/ArkUIKit/ScrollableComponent/screenshots/device/image3.png b/ArkUIKit/ScrollableComponent/screenshots/device/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..29676689f850c442159c7371319a739a126bb945 Binary files /dev/null and b/ArkUIKit/ScrollableComponent/screenshots/device/image3.png differ