diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/README_zh.md b/code/DocsSample/ArkUISample/ScrollableComponent/README_zh.md index 97bfaa656eba23b0edddc31c6c756c5a27a2d641..6050e802cce9f24ae08881941cd43fcd5a0d1704 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/README_zh.md +++ b/code/DocsSample/ArkUISample/ScrollableComponent/README_zh.md @@ -4,10 +4,13 @@ 本示例通过使用[ArkUI指南文档](https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/ui)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: -1. [创建列表 (List)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-layout-development-create-list.md)。 -2. [创建网格 (Grid/GridItem)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-layout-development-create-grid.md)。 -3. [创建轮播 (Swiper)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-layout-development-create-looping.md)。 -4. [选项卡 (Tabs)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/ui/arkts-navigation-tabs.md) +1. [创建列表 (List)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-layout-development-create-list.md)。 +2. [创建弧形列表 (ArcList)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-layout-development-create-arclist.md)(圆形屏幕推荐使用) +3. [创建网格 (Grid/GridItem)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-layout-development-create-grid.md)。 +4. [创建瀑布流 (WaterFlow)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-layout-development-create-waterflow.md) +5. [创建轮播 (Swiper)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-layout-development-create-looping.md)。 +6. [创建弧形轮播 (ArcSwiper)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-layout-development-arcswiper.md)(圆形屏幕推荐使用) +7. [选项卡 (Tabs)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.1.0-Release/zh-cn/application-dev/ui/arkts-navigation-tabs.md) ### 效果预览 | 首页 | 列表类组件目录 | 列表中显示数据示例 | @@ -29,31 +32,60 @@ 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 +| | |---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 @@ -69,7 +101,19 @@ entry/src/main/ets/ | | |---SideTabBar.ets | | |---SwipeLockedTabBar.ets | | |---TabsLayout.ets -| | |---TopTabBar.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/ @@ -89,9 +133,9 @@ entry/src/ohosTest/ 1.本示例仅支持标准系统上运行, 支持设备:RK3568。 -2.本示例为Stage模型,支持API14版本SDK,使用了系统接口updateConfiguration需要使用fullSDK,版本号:5.0.2.57,镜像版本号:OpenHarmony_5.0.2.57。 +2.本示例为Stage模型,支持API18版本SDK,版本号:5.1.0.107,镜像版本号:OpenHarmony_5.1.0 Release。 -3.本示例需要使用DevEco Studio NEXT Developer Preview2 (Build Version: 5.0.5.306, built on December 12, 2024)及以上版本才可编译运行。 +3.本示例需要使用DevEco Studio 5.0.5 Release (Build Version: 5.0.13.200, built on May 13, 2025)及以上版本才可编译运行。 ### 下载 diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/build-profile.json5 b/code/DocsSample/ArkUISample/ScrollableComponent/build-profile.json5 index 9a067264a40737cf79d1d8ae7c574b8d2cc87ce0..b17b9042c1982deb930f28d08cd5984488b13274 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/build-profile.json5 +++ b/code/DocsSample/ArkUISample/ScrollableComponent/build-profile.json5 @@ -20,9 +20,9 @@ { "name": "default", "signingConfig": "default", - "compileSdkVersion": 14, - "compatibleSdkVersion": 14, - "targetSdkVersion": 14, + "compileSdkVersion": 18, + "compatibleSdkVersion": 18, + "targetSdkVersion": 18, "runtimeOS": "OpenHarmony", "buildOption": { "strictMode": { diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/Index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/Index.ets index 340fa3185079b9fcf3a571a75f3f1c8e6b8e5a4f..be9cdd168523a39eec9f2753548c165d168b2da0 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/Index.ets +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/Index.ets @@ -19,7 +19,10 @@ 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[] = [ @@ -27,14 +30,26 @@ 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 @@ -49,8 +64,14 @@ function destination(name: string) { 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); } } @@ -107,4 +128,4 @@ struct Index { }) .navDestination(destination) } -} +} \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListAcrScrollBar.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListAcrScrollBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..6cb9df1e993b96d6c2dd6864df78c656fad4c23d --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListArcIndexerBar.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListArcIndexerBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..ca16ea3554d04747c3e6b5d323ab0bb5f56d9442 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListContents.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListContents.ets new file mode 100644 index 0000000000000000000000000000000000000000..007f3911dd50fe7ca9eaa42f51c2be455f09b0ad --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListCrown.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListCrown.ets new file mode 100644 index 0000000000000000000000000000000000000000..cc76cdd3cb9dcb943ca881973e60b9eb965a8712 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListShow.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListShow.ets new file mode 100644 index 0000000000000000000000000000000000000000..932600a062460483ac317ddba7abce9249dbe6bc --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListSideSlip.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListSideSlip.ets new file mode 100644 index 0000000000000000000000000000000000000000..ce364a1d3495111550eda7d0bca4206abf81f1f9 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListStyles.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcListStyles.ets new file mode 100644 index 0000000000000000000000000000000000000000..d3452e6ba7f8f05c5df4a15dee0d94cab2ff54b7 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcLongList.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/ArcLongList.ets new file mode 100644 index 0000000000000000000000000000000000000000..6ddd21ef91d42add85eb674413d50693f0df0a36 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/arcListBuiltInScrollerBar.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/arcListBuiltInScrollerBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..f38604db4abcad1d3eb7fe6d91386fcb1c9d411f --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcList/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b2b874b86cf2ef6da31a8d4aa1a8d3ac845e95fd --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperAction.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperAction.ets new file mode 100644 index 0000000000000000000000000000000000000000..d7f1f0af987e314896998fd453ee0d0905692d02 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperHorizontal.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperHorizontal.ets new file mode 100644 index 0000000000000000000000000000000000000000..47d538edcbc3bac7bba2cea7f8e10c588061d6b0 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperSideSlip.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperSideSlip.ets new file mode 100644 index 0000000000000000000000000000000000000000..af64879aee82cd2758e3bab79a60b911c54b904e --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperStyles.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperStyles.ets new file mode 100644 index 0000000000000000000000000000000000000000..11bf5dd57c629e5e812e2d555e3e8d07c1f51a1a --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperToggle.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperToggle.ets new file mode 100644 index 0000000000000000000000000000000000000000..143dab03e084c9835a635891065543a62626a1f9 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperVertical.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/ArcSwiperVertical.ets new file mode 100644 index 0000000000000000000000000000000000000000..4e27070ed8f885ad6ff9a12113450e85ffa0c8cd --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/arcSwiper/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..98f58400da894b77fff2a7d89bdfb7767f2b6d0b --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/GridDataSource.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/GridDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..f0d9e9bb8052f2cd52e3d4623f0aa6b9166707ae --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/GridScrollbar.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/GridScrollbar.ets new file mode 100644 index 0000000000000000000000000000000000000000..74443ede7231b3c0ef3b7f976a730a51cb05e45c --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/GridSideToSide.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/GridSideToSide.ets new file mode 100644 index 0000000000000000000000000000000000000000..fd30401da34682d2b17f44b8411c2cb5d81de55a --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/LongGrid.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/LongGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..073655c3e3024bba52fa4496f8f9ece2e03c2774 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets index 488e6b32995892948794fa5dbb52f6df900b8a7f..99fc49c2e440fb3a2d5ed55f11157005ee7b7527 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/grid/index.ets @@ -19,6 +19,9 @@ 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 resource from '../../common/resource'; export const GRID_ROUTE_PREFIX: string = 'grid'; @@ -43,6 +46,21 @@ const routes: Route[] = [ 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') } ]; @@ -58,6 +76,12 @@ export function gridDestination(name: string) { 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(); } } diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/CollapseAndExpand.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/CollapseAndExpand.ets new file mode 100644 index 0000000000000000000000000000000000000000..52fd69387c7086e8b86b6aff6b4e075f119a6f3b --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets index 9ae3c492d8c128b398d6e08124dca5a7e67e9e64..fbc9b904b59bc686e7158a4b6355c0c8091880cd 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/Index.ets @@ -27,6 +27,9 @@ 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'; @@ -91,6 +94,21 @@ const routes: Route[] = [ 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') } ]; @@ -122,6 +140,12 @@ export function listDestination(name: string) { 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(); } } diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/ListChatRoom.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/ListChatRoom.ets new file mode 100644 index 0000000000000000000000000000000000000000..f71e5b69ea6f1359b877688bee7de8f97092fe9f --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/ListDataSource.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/ListDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..07e4de1fe56f77093f568dca498e66235f0e6191 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/LongList.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/list/LongList.ets new file mode 100644 index 0000000000000000000000000000000000000000..6c5fd86c5de5d90eab101c5a74fe607903e1b9ee --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAndTabsLinkage.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperAndTabsLinkage.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b6320ccd976e470890217dae13cd3d61caa0ce2 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIgnoreComponentSize.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/SwiperIgnoreComponentSize.ets new file mode 100644 index 0000000000000000000000000000000000000000..420343eb510941dde4c0e9565b2d06c0df0124ef --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets index fb4fe1192da6b89fe6a7ef334cb0bdc746b952bb..37aa2ea07443fc9bb7f149c03d90906f217a4379 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/swiper/index.ets @@ -22,6 +22,7 @@ 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'; @@ -61,6 +62,11 @@ const routes: Route[] = [ 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') } ]; @@ -82,6 +88,8 @@ export function swiperDestination(name: string) { SwiperMultiPage(); } else if (name === routes[6].name) { SwiperCustomAnimation(); + } else if (name === routes[7].name) { + SwiperAndTabsLinkage(); } } diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDataSource.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..ef8f873f793ecc7e3ecc1525832c4036c454cce4 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDataSource.ets @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { + let len = this.dataArray.length; + for (let i = 0; i < count; i++) { + this.dataArray.push(this.dataArray.length); + } + this.listeners.forEach(listener => { + listener.onDatasetChange([{ type: DataOperationType.ADD, index: len, count: count }]); + }) + } + + // 在指定索引位置增加一个元素 + 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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDynamicSwitchover.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowDynamicSwitchover.ets new file mode 100644 index 0000000000000000000000000000000000000000..6c7ccb83c5a000e1af44dc02091fbe3b1475b9ce --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowGroupingMixing.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowGroupingMixing.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f5fcc388c75a2ff187f8ffa7f5d49b1fd8b1488 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrolling.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrolling.ets new file mode 100644 index 0000000000000000000000000000000000000000..090bdf39b81bc3ba995ca1617cc95492d8cdcb44 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrollingEarly.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/WaterFlowInfiniteScrollingEarly.ets new file mode 100644 index 0000000000000000000000000000000000000000..162cb8e756fd1ce79512599c73e712d7ab1f0d1c --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/index.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/pages/waterFlow/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..d7c2f53083ee3356cb30e453c41c0ed9b9b3bbfc --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(0).JPG b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(0).JPG new file mode 100644 index 0000000000000000000000000000000000000000..fc503bbffd260e135a6d1b8050ae8270b5b7b334 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(0).JPG differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(1).JPG b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(1).JPG new file mode 100644 index 0000000000000000000000000000000000000000..1085f839befca033a2687c554a47d535d589dc59 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(1).JPG differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(2).JPG b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(2).JPG new file mode 100644 index 0000000000000000000000000000000000000000..680348896f729a6b7d3860613403485a5a3090b7 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(2).JPG differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(3).JPG b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(3).JPG new file mode 100644 index 0000000000000000000000000000000000000000..0805dade041dc79b2dbc336f104fbaa8c86186e7 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(3).JPG differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(4).JPG b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(4).JPG new file mode 100644 index 0000000000000000000000000000000000000000..1ee3676323ab5637c00f5d486e72f5d6776e85a7 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(4).JPG differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(5).JPG b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(5).JPG new file mode 100644 index 0000000000000000000000000000000000000000..f1488adf937caeaf3b70a6d43d5fb228e15e1d37 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/ets/res/waterFlow(5).JPG differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/element/string.json b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/element/string.json index a15c593221ea927d8a9e90df2e45cf69cf3138f9..70ae02de85d68365db31274ceac2430cd53d9ff6 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/element/string.json +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/element/string.json @@ -16,6 +16,10 @@ "name": "pageIndex_List", "value": "列表/List" }, + { + "name": "pageIndex_ArcList", + "value": "弧形列表/ArcList" + }, { "name": "pageIndex_Grid", "value": "网格/Grid" @@ -24,6 +28,10 @@ "name": "pageIndex_Swiper", "value": "轮播/Swiper" }, + { + "name": "pageIndex_ArcSwiper", + "value": "弧形轮播/ArcSwiper" + }, { "name": "pageIndex_Tabs", "value": "选项卡/Tabs" @@ -699,6 +707,274 @@ { "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": "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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/MaterialSymbolsDelete.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/MaterialSymbolsDelete.svg new file mode 100644 index 0000000000000000000000000000000000000000..8f8348613dafc3fb1a1adbaa0f978bd3e9398fd7 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/MaterialSymbolsDelete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/background.png b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/background.png index f939c9fa8cc8914832e602198745f592a0dfa34d..923f2b3f27e915d6871871deea0420eb45ce102f 100644 Binary files a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/background.png and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/background.png differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/blueTooth.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/blueTooth.svg new file mode 100644 index 0000000000000000000000000000000000000000..0fbcf2bd2720f8bc33ce34552ff07b0238523088 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/blueTooth.svg @@ -0,0 +1,16 @@ + + + 编组 + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/delete.png b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..1714478bde5bd46fa9856e0ebc06be459c4664f2 Binary files /dev/null and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/delete.png differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/displayAndBrightness.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/displayAndBrightness.svg new file mode 100644 index 0000000000000000000000000000000000000000..c19e018d71201ed17e239da5851bde5a9cfaf12a --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/displayAndBrightness.svg @@ -0,0 +1,16 @@ + + + 编组 + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/foreground.png index 4483ddad1f079e1089d685bd204ee1cfe1d01902..97014d3e10e5ff511409c378cd4255713aecd85f 100644 Binary files a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/foreground.png and b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/foreground.png differ diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_contact.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_contact.svg new file mode 100644 index 0000000000000000000000000000000000000000..45128f1a45c7f70b96217f8a840eb6ca922f5e56 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_contact.svg @@ -0,0 +1,21 @@ + + + 默认头像icon + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_arrow.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_arrow.svg new file mode 100644 index 0000000000000000000000000000000000000000..ff6293ce432d79ed6c50d61d430ee79fe2e2dad2 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_arrow.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_more_connections.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_more_connections.svg new file mode 100644 index 0000000000000000000000000000000000000000..7e654cf2401d3f4c5db1c971fcefb28af119ef2a --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_wifi.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/ic_settings_wifi.svg new file mode 100644 index 0000000000000000000000000000000000000000..53dadba1d2dac8ca8b98697705edb004874404c5 --- /dev/null +++ b/code/DocsSample/ArkUISample/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/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/mobileData.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/mobileData.svg new file mode 100644 index 0000000000000000000000000000000000000000..3af781748dbcef004e85fc31d92da3175b21c6c1 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/mobileData.svg @@ -0,0 +1,19 @@ + + + 编组 10 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/wlan.svg b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/wlan.svg new file mode 100644 index 0000000000000000000000000000000000000000..be12071bad8d8780bf172fb777cc7bf5c76e5a57 --- /dev/null +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/main/resources/base/media/wlan.svg @@ -0,0 +1,16 @@ + + + 编组 17 + + + + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets index cda9bf95ad453d8b67e61aea7d7aae1dedb14653..30b111830deafd1cbbb852db21fa483d02371daa 100644 --- a/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets +++ b/code/DocsSample/ArkUISample/ScrollableComponent/entry/src/ohosTest/ets/test/index.test.ets @@ -629,5 +629,696 @@ export default function IndexTest() { 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/code/DocsSample/ArkUISample/ScrollableComponent/screenshots/device/image1.png b/code/DocsSample/ArkUISample/ScrollableComponent/screenshots/device/image1.png index e23ff56545af37c7ebde9006c8bbab718ce3cc4d..405d7c9a85730a32a35eb1e90e09dfed55114733 100644 Binary files a/code/DocsSample/ArkUISample/ScrollableComponent/screenshots/device/image1.png and b/code/DocsSample/ArkUISample/ScrollableComponent/screenshots/device/image1.png differ