【中工开辟者】鸿蒙------电子相册

打印 上一主题 下一主题

主题 988|帖子 988|积分 2964

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目次
简介
相干概念
相干权限
使用阐明
项目环境
 运行截图
代码示例
 DetailPage
方法
aboutToAppear
resetImg
handlePanEnd
DetailListPage
交互逻辑
UI 结构
IndexPage
 标题栏 (Row)
轮播图 (Swiper) 
ListPage
 网格结构 (Grid)

简介

  本学期学习了鸿蒙开辟课程,在课程学习中收获良多,用一个小项目分享一些学习成果。
  本项目是基于ArkTS实现的一个电子相册案例,通过捏合和拖拽手势控制图片的放大、缩小、左右拖动检察细节等效果。

相干概念



  • Swiper:滑块视图容器,提供子组件滑动轮播表现的能力。
  • Grid:网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的结构。
  • Navigation:Navigation组件一般作为Page页面的根容器,通过属性设置来展示页面的标题、工具栏、菜单。
  • List:列表包罗一系列雷同宽度的列表项。得当连续、多行出现同类数据,例如图片和文本。
  • 组合手势:手势识别组,多种手势组合为复合手势,支持连续识别、并行识别和互斥识别。
相干权限

不涉及
使用阐明


  • 用户可以使用捏合手势实现图片的放大缩小。
  • 用户可以通过滑动手势实现图片的左右切换。
  • 用户可以在图片放大的底子上,可以通过拖拽手势对图片进行拖拽检察细节。
项目环境


  • HarmonyOS系统:HarmonyOS NEXT Developer Beta1及以上。
  • DevEco Studio版本:DevEco Studio NEXT Developer Beta1及以上。
  • HarmonyOS SDK版本:HarmonyOS NEXT Developer Beta1 SDK及以上。
 运行截图





代码示例

 DetailPage

 

  1. @Entry
  2. @Component
  3. struct DetailPage {
  4.   scroller: Scroller = new Scroller();
  5.   photoArr: Array<Resource> = (router.getParams() as Record<string, Array<Resource>>)[`${Constants.PARAM_PHOTO_ARR_KEY}`];
  6.   preOffsetX: number = 0;
  7.   preOffsetY: number = 0;
  8.   currentScale: number = 1;
  9.   @State deviceWidth: number = Constants.DEFAULT_WIDTH;
  10.   @State smallImgWidth: number = (Constants.DEFAULT_WIDTH - Constants.LIST_ITEM_SPACE * (Constants.SHOW_COUNT - 1)) /
  11.   Constants.SHOW_COUNT;
  12.   @State imageWidth: number = this.deviceWidth + this.smallImgWidth;
  13.   @StorageLink('selectedIndex') selectedIndex: number = 0;
  14.   @State isScaling: boolean = true;
  15.   @State imgScale: number = 1;
  16.   @State imgOffSetX: number = 0;
  17.   @State imgOffSetY: number = 0;
  18.   @State bgOpacity: number = 0;
  19.   aboutToAppear() {
  20.     let displayClass: display.Display = display.getDefaultDisplaySync();
  21.     let width = displayClass?.width / displayClass.densityPixels ?? Constants.DEFAULT_WIDTH;
  22.     this.deviceWidth = width;
  23.     this.smallImgWidth = (width - Constants.LIST_ITEM_SPACE * (Constants.SHOW_COUNT - 1)) / Constants.SHOW_COUNT;
  24.     this.imageWidth = this.deviceWidth + this.smallImgWidth;
  25.   }
  26.   resetImg(): void {
  27.     this.imgScale = 1;
  28.     this.currentScale = 1;
  29.     this.preOffsetX = 0;
  30.     this.preOffsetY = 0;
  31.   }
  32.   handlePanEnd(): void {
  33.     let initOffsetX = (this.imgScale - 1) * this.imageWidth + this.smallImgWidth;
  34.     if (Math.abs(this.imgOffSetX) > initOffsetX) {
  35.       if (this.imgOffSetX > initOffsetX && this.selectedIndex > 0) {
  36.         this.selectedIndex -= 1;
  37.       } else if (this.imgOffSetX < -initOffsetX && this.selectedIndex < (this.photoArr.length - 1)) {
  38.         this.selectedIndex += 1;
  39.       }
  40.       this.isScaling = false;
  41.       this.resetImg();
  42.       this.scroller.scrollTo({ xOffset: this.selectedIndex * this.imageWidth, yOffset: 0 });
  43.     }
  44.   }
  45.   build() {
  46.     Stack() {
  47.       List({ scroller: this.scroller, initialIndex: this.selectedIndex }) {
  48.         ForEach(this.photoArr, (img: Resource) => {
  49.           ListItem() {
  50.             Image(img)
  51.               .objectFit(ImageFit.Contain)
  52.               .onClick(() => router.back())
  53.           }
  54.           .gesture(GestureGroup(GestureMode.Exclusive,
  55.             PinchGesture({ fingers: Constants.DOUBLE_NUMBER })
  56.               .onActionStart(() => {
  57.                 this.resetImg();
  58.                 this.isScaling = true;
  59.                 this.imgOffSetX = 0;
  60.                 this.imgOffSetY = 0;
  61.               })
  62.               .onActionUpdate((event?: GestureEvent) => {
  63.                 if (event) {
  64.                   this.imgScale = this.currentScale * event.scale;
  65.                 }
  66.               })
  67.               .onActionEnd(() => {
  68.                 if (this.imgScale < 1) {
  69.                   this.resetImg();
  70.                   this.imgOffSetX = 0;
  71.                   this.imgOffSetY = 0;
  72.                 } else {
  73.                   this.currentScale = this.imgScale;
  74.                 }
  75.               }), PanGesture()
  76.               .onActionStart(() => {
  77.                 this.resetImg();
  78.                 this.isScaling = true;
  79.               })
  80.               .onActionUpdate((event?: GestureEvent) => {
  81.                 if (event) {
  82.                   this.imgOffSetX = this.preOffsetX + event.offsetX;
  83.                   this.imgOffSetY = this.preOffsetY + event.offsetY;
  84.                 }
  85.               })
  86.           ))
  87.           .padding({
  88.             left: this.smallImgWidth / Constants.DOUBLE_NUMBER,
  89.             right: this.smallImgWidth / Constants.DOUBLE_NUMBER
  90.           })
  91.           .width(this.imageWidth)
  92.         }, (item: Resource) => JSON.stringify(item))
  93.       }
  94.       .onScrollStop(() => {
  95.         let currentIndex = Math.round(((this.scroller.currentOffset().xOffset as number) +
  96.           (this.imageWidth / Constants.DOUBLE_NUMBER)) / this.imageWidth);
  97.         this.selectedIndex = currentIndex;
  98.         this.scroller.scrollTo({ xOffset: currentIndex * this.imageWidth, yOffset: 0 });
  99.       })
  100.       .width(Constants.FULL_PERCENT)
  101.       .height(Constants.FULL_PERCENT)
  102.       .listDirection(Axis.Horizontal)
  103.       .visibility(this.isScaling ? Visibility.Hidden : Visibility.Visible)
  104.       Row() {
  105.         Image(this.photoArr[this.selectedIndex])
  106.           .position({ x: this.imgOffSetX, y: this.imgOffSetY })
  107.           .scale({ x: this.imgScale, y: this.imgScale })
  108.           .objectFit(ImageFit.Contain)
  109.           .onClick(() => router.back())
  110.       }
  111.       .gesture(GestureGroup(GestureMode.Exclusive,
  112.         PinchGesture({ fingers: Constants.DOUBLE_NUMBER })
  113.           .onActionUpdate((event?: GestureEvent) => {
  114.             if (event) {
  115.               this.imgScale = this.currentScale * event.scale;
  116.             }
  117.           })
  118.           .onActionEnd(() => {
  119.             if (this.imgScale < 1) {
  120.               this.resetImg();
  121.               this.imgOffSetX = 0;
  122.               this.imgOffSetY = 0;
  123.             } else {
  124.               this.currentScale = this.imgScale;
  125.             }
  126.           }),
  127.         PanGesture()
  128.           .onActionStart(() => {
  129.             this.preOffsetX = this.imgOffSetX;
  130.             this.preOffsetY = this.imgOffSetY;
  131.           })
  132.           .onActionUpdate((event?: GestureEvent) => {
  133.             if (event) {
  134.               this.imgOffSetX = this.preOffsetX + event.offsetX;
  135.               this.imgOffSetY = this.preOffsetY + event.offsetY;
  136.             }
  137.           })
  138.           .onActionEnd(() => this.handlePanEnd())
  139.       ))
  140.       .padding({
  141.         left: this.smallImgWidth / Constants.DOUBLE_NUMBER,
  142.         right: this.smallImgWidth / Constants.DOUBLE_NUMBER
  143.       })
  144.       .width(this.imageWidth)
  145.       .height(Constants.FULL_PERCENT)
  146.       .visibility(this.isScaling ? Visibility.Visible : Visibility.Hidden)
  147.     }
  148.     .offset({ x: -(this.smallImgWidth / Constants.DOUBLE_NUMBER) })
  149.     .width(this.imageWidth)
  150.     .height(Constants.FULL_PERCENT)
  151.     .backgroundColor($r('app.color.detail_background'))
  152.   }
  153. }
复制代码
这段代码定义了用于表现一组图片,并允许用户通过手势进行缩放和平移。该组件使用了鸿蒙操作系统(HarmonyOS)的声明式UI框架ArkUI来构建。
方法

aboutToAppear

这个方法会在组件即将出如今屏幕上时调用,用来初始化一些依赖于屏幕尺寸的状态变量。
resetImg

重置图像的缩放和平移值到默认状态。
handlePanEnd

当用户结束拖动手势时调用此方法。根据用户的拖动距离和方向调整 selectedIndex 并重置图像状态,同时滚动到新的选定图像位置。
DetailListPage


  1. @Entry
  2. @Component
  3. struct DetailListPage {
  4.   private smallScroller: Scroller = new Scroller();
  5.   private bigScroller: Scroller = new Scroller();
  6.   @State deviceWidth: number = Constants.DEFAULT_WIDTH;
  7.   @State smallImgWidth: number = (this.deviceWidth - Constants.LIST_ITEM_SPACE * (Constants.SHOW_COUNT - 1)) /
  8.   Constants.SHOW_COUNT;
  9.   @State imageWidth: number = this.deviceWidth + this.smallImgWidth;
  10.   private photoArr: Array<Resource | string> = (router.getParams() as Record<string, Array<Resource | string>>)[`${Constants.PARAM_PHOTO_ARR_KEY}`];
  11.   private smallPhotoArr: Array<Resource | string> = new Array<Resource | string>().concat(Constants.CACHE_IMG_LIST,
  12.     (router.getParams() as Record<string, Array<Resource | string>>)[`${Constants.PARAM_PHOTO_ARR_KEY}`],
  13.     Constants.CACHE_IMG_LIST)
  14.   @StorageLink('selectedIndex') selectedIndex: number = 0;
  15.   @Builder SmallImgItemBuilder(img: Resource, index?: number) {
  16.     if (index && index > (Constants.CACHE_IMG_SIZE - 1) && index < (this.smallPhotoArr.length - Constants.CACHE_IMG_SIZE)) {
  17.       Image(img)
  18.         .onClick(() => this.smallImgClickAction(index))
  19.     }
  20.   }
  21.   aboutToAppear() {
  22.     let displayClass: display.Display = display.getDefaultDisplaySync();
  23.     let width = displayClass?.width / displayClass.densityPixels ?? Constants.DEFAULT_WIDTH;
  24.     this.deviceWidth = width;
  25.     this.smallImgWidth = (width - Constants.LIST_ITEM_SPACE * (Constants.SHOW_COUNT - 1)) / Constants.SHOW_COUNT;
  26.     this.imageWidth = this.deviceWidth + this.smallImgWidth;
  27.   }
  28.   onPageShow() {
  29.     this.smallScroller.scrollToIndex(this.selectedIndex);
  30.     this.bigScroller.scrollToIndex(this.selectedIndex);
  31.   }
  32.   goDetailPage(): void {
  33.     router.pushUrl({
  34.       url: Constants.URL_DETAIL_PAGE,
  35.       params: { photoArr: this.photoArr }
  36.     });
  37.   }
  38.   smallImgClickAction(index: number): void {
  39.     this.selectedIndex = index - Constants.CACHE_IMG_SIZE;
  40.     this.smallScroller.scrollToIndex(this.selectedIndex);
  41.     this.bigScroller.scrollToIndex(this.selectedIndex);
  42.   }
  43.   smallScrollAction(type: scrollTypeEnum): void {
  44.     this.selectedIndex = Math.round(((this.smallScroller.currentOffset().xOffset as number) +
  45.     this.smallImgWidth / Constants.DOUBLE_NUMBER) / (this.smallImgWidth + Constants.LIST_ITEM_SPACE));
  46.     if (type === scrollTypeEnum.SCROLL) {
  47.       this.bigScroller.scrollTo({ xOffset: this.selectedIndex * this.imageWidth, yOffset: 0 });
  48.     } else {
  49.       this.smallScroller.scrollTo({ xOffset: this.selectedIndex * this.smallImgWidth, yOffset: 0 });
  50.     }
  51.   }
  52.   bigScrollAction(type: scrollTypeEnum): void {
  53.     let smallWidth = this.smallImgWidth + Constants.LIST_ITEM_SPACE;
  54.     this.selectedIndex = Math.round(((this.bigScroller.currentOffset().xOffset as number) +
  55.       smallWidth / Constants.DOUBLE_NUMBER) / this.imageWidth);
  56.     if (type === scrollTypeEnum.SCROLL) {
  57.       this.smallScroller.scrollTo({ xOffset: this.selectedIndex * smallWidth, yOffset: 0 });
  58.     } else {
  59.       this.bigScroller.scrollTo({ xOffset: this.selectedIndex * this.imageWidth, yOffset: 0 });
  60.     }
  61.   }
  62.   build() {
  63.     Navigation() {
  64.       Stack({ alignContent: Alignment.Bottom }) {
  65.         List({ scroller: this.bigScroller, initialIndex: this.selectedIndex }) {
  66.           ForEach(this.photoArr, (img: Resource) => {
  67.             ListItem() {
  68.               Image(img)
  69.                 .height(Constants.FULL_PERCENT)
  70.                 .width(Constants.FULL_PERCENT)
  71.                 .objectFit(ImageFit.Contain)
  72.                 .gesture(PinchGesture({ fingers: Constants.DOUBLE_NUMBER })
  73.                   .onActionStart(() => this.goDetailPage()))
  74.                 .onClick(() => this.goDetailPage())
  75.             }
  76.             .padding({
  77.               left: this.smallImgWidth / Constants.DOUBLE_NUMBER,
  78.               right: this.smallImgWidth / Constants.DOUBLE_NUMBER
  79.             })
  80.             .width(this.imageWidth)
  81.           }, (item: Resource) => JSON.stringify(item))
  82.         }
  83.         .onScroll((scrollOffset, scrollState) => {
  84.           if (scrollState === ScrollState.Fling) {
  85.             this.bigScrollAction(scrollTypeEnum.SCROLL);
  86.           }
  87.         })
  88.         .scrollBar(BarState.Off)
  89.         .onScrollStop(() => this.bigScrollAction(scrollTypeEnum.STOP))
  90.         .width(Constants.FULL_PERCENT)
  91.         .height(Constants.FULL_PERCENT)
  92.         .padding({ bottom: this.smallImgWidth * Constants.DOUBLE_NUMBER })
  93.         .listDirection(Axis.Horizontal)
  94.         List({
  95.           scroller: this.smallScroller,
  96.           space: Constants.LIST_ITEM_SPACE,
  97.           initialIndex: this.selectedIndex
  98.         }) {
  99.           ForEach(this.smallPhotoArr, (img: Resource, index?: number) => {
  100.             ListItem() {
  101.               this.SmallImgItemBuilder(img, index)
  102.             }
  103.             .width(this.smallImgWidth)
  104.             .aspectRatio(1)
  105.           }, (item: Resource) => JSON.stringify(item))
  106.         }
  107.         .listDirection(Axis.Horizontal)
  108.         .onScroll((scrollOffset, scrollState) => {
  109.           if (scrollState === ScrollState.Fling) {
  110.             this.smallScrollAction(scrollTypeEnum.SCROLL);
  111.           }
  112.         })
  113.         .scrollBar(BarState.Off)
  114.         .onScrollStop(() => this.smallScrollAction(scrollTypeEnum.STOP))
  115.         .margin({ top: $r('app.float.detail_list_margin'), bottom: $r('app.float.detail_list_margin') })
  116.         .height(this.smallImgWidth)
  117.         .width(Constants.FULL_PERCENT)
  118.       }
  119.       .width(this.imageWidth)
  120.       .height(Constants.FULL_PERCENT)
  121.     }
  122.     .title(Constants.PAGE_TITLE)
  123.     .hideBackButton(false)
  124.     .titleMode(NavigationTitleMode.Mini)
  125.   }
  126. }
复制代码
 这段代码是一个包罗两个程度滚动列表的页面:一个用于表现较大的图片(bigScroller),另一个用于表现较小的缩略图(smallScroller)。用户可以通过点击缩略图来切换大图,或者直接在大图上进行交互。
交互逻辑

  1. goDetailPage(): void {
  2.   // 导航到详情页
  3. }
  4. smallImgClickAction(index: number): void {
  5.   // 更新选中索引并滚动到对应位置
  6. }
  7. smallScrollAction(type: scrollTypeEnum): void {
  8.   // 根据滚动类型更新索引和滚动位置
  9. }
  10. bigScrollAction(type: scrollTypeEnum): void {
  11.   // 根据滚动类型更新索引和滚动位置
  12. }
复制代码
UI 结构

  1. build() {
  2.   Navigation() {
  3.     Stack({ alignContent: Alignment.Bottom }) {
  4.       // 大图列表
  5.       List({ scroller: this.bigScroller, initialIndex: this.selectedIndex }) {
  6.         // ...
  7.       }
  8.       // 小图列表
  9.       List({
  10.         scroller: this.smallScroller,
  11.         space: Constants.LIST_ITEM_SPACE,
  12.         initialIndex: this.selectedIndex
  13.       }) {
  14.         // ...
  15.       }
  16.     }
  17.   }
  18.   .title(Constants.PAGE_TITLE)
  19.   .hideBackButton(false)
  20.   .titleMode(NavigationTitleMode.Mini)
  21. }
复制代码


  • Navigation 包装整个结构,并设置了标题栏配置。
  • Stack 用于堆叠大图列表和小图列表。
  • 每个 List 都有自己的滚动控制器 (scroller) 并绑定了滚动变乱监听器,以同步两个列表之间的滚动状态。
  • ForEach 循环生成列表项,每个项目都绑定有手势识别或点击变乱处理步调。
IndexPage

 

  1. @Entry
  2. @Component
  3. struct IndexPage {
  4.   swiperController: SwiperController = new SwiperController();
  5.   scroller: Scroller = new Scroller();
  6.   @State currentIndex: number = 0;
  7.   @State angle: number = 0;
  8.   build() {
  9.     Column() {
  10.       Row() {
  11.         Text($r('app.string.EntryAbility_label'))
  12.           .fontSize($r('app.float.title_font_size'))
  13.           .fontWeight(Constants.TITLE_FONT_WEIGHT)
  14.       }
  15.       .height($r('app.float.navi_bar_height'))
  16.       .alignItems(VerticalAlign.Center)
  17.       .justifyContent(FlexAlign.Start)
  18.       .margin({ top: $r('app.float.grid_padding') })
  19.       .padding({ left: $r('app.float.title_padding') })
  20.       .width(Constants.FULL_PERCENT)
  21.       Swiper(this.swiperController) {
  22.         ForEach(Constants.BANNER_IMG_LIST, (item: Resource) => {
  23.           Row() {
  24.             Image(item)
  25.               .width(Constants.FULL_PERCENT)
  26.               .height(Constants.FULL_PERCENT)
  27.           }
  28.           .width(Constants.FULL_PERCENT)
  29.           .aspectRatio(Constants.BANNER_ASPECT_RATIO)
  30.         }, (item: Resource, index?: number) => JSON.stringify(item) + index)
  31.       }
  32.       .autoPlay(true)
  33.       .loop(true)
  34.       .margin($r('app.float.grid_padding'))
  35.       .borderRadius($r('app.float.img_border_radius'))
  36.       .clip(true)
  37.       .duration(Constants.BANNER_ANIMATE_DURATION)
  38.       .indicator(false)
  39.       Grid() {
  40.         ForEach(Constants.IMG_ARR, (photoArr: Array<Resource>) => {
  41.           GridItem() {
  42.             PhotoItem({ photoArr })
  43.           }
  44.           .width(Constants.FULL_PERCENT)
  45.           .aspectRatio(Constants.STACK_IMG_RATIO)
  46.           .onClick(() => {
  47.             router.pushUrl({
  48.               url: Constants.URL_LIST_PAGE,
  49.               params: { photoArr: photoArr }
  50.             });
  51.           })
  52.         }, (item: Resource, index?: number) => JSON.stringify(item) + index)
  53.       }
  54.       .scrollBar(BarState.Off)
  55.       .columnsTemplate(Constants.INDEX_COLUMNS_TEMPLATE)
  56.       .columnsGap($r('app.float.grid_padding'))
  57.       .rowsGap($r('app.float.grid_padding'))
  58.       .padding({ left: $r('app.float.grid_padding'), right: $r('app.float.grid_padding') })
  59.       .width(Constants.FULL_PERCENT)
  60.       .layoutWeight(1)
  61.     }
  62.     .width(Constants.FULL_PERCENT)
  63.     .height(Constants.FULL_PERCENT)
  64.   }
  65. }
复制代码
 这段代码定义了应用的首页或入口页面,包罗顶部的文字标题、一个轮播图(Swiper)和一个网格结构(Grid)。
 标题栏 (Row)

  1. Row() {
  2.   Text($r('app.string.EntryAbility_label'))
  3.     .fontSize($r('app.float.title_font_size'))
  4.     .fontWeight(Constants.TITLE_FONT_WEIGHT)
  5. }
  6. .height($r('app.float.navi_bar_height'))
  7. .alignItems(VerticalAlign.Center)
  8. .justifyContent(FlexAlign.Start)
  9. .margin({ top: $r('app.float.grid_padding') })
  10. .padding({ left: $r('app.float.title_padding') })
  11. .width(Constants.FULL_PERCENT)
复制代码


  • 创建一个行容器 Row 来放置文本 Text,用作页面标题。
  • 设置了字体大小、权重,并调整了结构属性如高度、对齐方式、边距和内边距。
轮播图 (Swiper) 

  1. Swiper(this.swiperController) {
  2.   ForEach(Constants.BANNER_IMG_LIST, (item: Resource) => {
  3.     Row() {
  4.       Image(item)
  5.         .width(Constants.FULL_PERCENT)
  6.         .height(Constants.FULL_PERCENT)
  7.     }
  8.     .width(Constants.FULL_PERCENT)
  9.     .aspectRatio(Constants.BANNER_ASPECT_RATIO)
  10.   }, (item: Resource, index?: number) => JSON.stringify(item) + index)
  11. }
  12. .autoPlay(true)
  13. .loop(true)
  14. .margin($r('app.float.grid_padding'))
  15. .borderRadius($r('app.float.img_border_radius'))
  16. .clip(true)
  17. .duration(Constants.BANNER_ANIMATE_DURATION)
  18. .indicator(false)
复制代码


  • 使用 Swiper 组件创建一个自动播放且循环的轮播图。
  • ForEach 循环遍历 Constants.BANNER_IMG_LIST 数组来生成轮播项。
ListPage

 

  1. @Entry
  2. @Component
  3. struct ListPage {
  4.   photoArr: Array<Resource> = (router.getParams() as Record<string, Array<Resource>>)[`${Constants.PARAM_PHOTO_ARR_KEY}`];
  5.   @StorageLink('selectedIndex') selectedIndex: number = 0;
  6.   build() {
  7.     Navigation() {
  8.       Grid() {
  9.         ForEach(this.photoArr, (img: Resource, index?: number) => {
  10.           GridItem() {
  11.             Image(img)
  12.               .height(Constants.FULL_PERCENT)
  13.               .width(Constants.FULL_PERCENT)
  14.               .objectFit(ImageFit.Cover)
  15.               .onClick(() => {
  16.                 if (!index) {
  17.                   index = 0;
  18.                 }
  19.                 this.selectedIndex = index;
  20.                 router.pushUrl({
  21.                   url: Constants.URL_DETAIL_LIST_PAGE,
  22.                   params: {
  23.                     photoArr: this.photoArr,
  24.                   }
  25.                 });
  26.               })
  27.           }
  28.           .width(Constants.FULL_PERCENT)
  29.           .aspectRatio(1)
  30.         }, (item: Resource) => JSON.stringify(item))
  31.       }
  32.       .scrollBar(BarState.Off)
  33.       .columnsTemplate(Constants.GRID_COLUMNS_TEMPLATE)
  34.       .rowsGap(Constants.LIST_ITEM_SPACE)
  35.       .columnsGap(Constants.LIST_ITEM_SPACE)
  36.       .layoutWeight(1)
  37.     }
  38.     .title(Constants.PAGE_TITLE)
  39.     .hideBackButton(false)
  40.     .titleMode(NavigationTitleMode.Mini)
  41.   }
  42. }
复制代码
 这段代码定义了一个列表页面,用于展示一组图片。这个页面从上一页接收参数,并根据这些参数来加载和表现对应的图片列表。
 网格结构 (Grid)

  1. Grid() {
  2.   ForEach(this.photoArr, (img: Resource, index?: number) => {
  3.     GridItem() {
  4.       Image(img)
  5.         .height(Constants.FULL_PERCENT)
  6.         .width(Constants.FULL_PERCENT)
  7.         .objectFit(ImageFit.Cover)
  8.         .onClick(() => {
  9.           if (!index) {
  10.             index = 0;
  11.           }
  12.           this.selectedIndex = index;
  13.           router.pushUrl({
  14.             url: Constants.URL_DETAIL_LIST_PAGE,
  15.             params: {
  16.               photoArr: this.photoArr,
  17.             }
  18.           });
  19.         })
  20.     }
  21.     .width(Constants.FULL_PERCENT)
  22.     .aspectRatio(1)
  23.   }, (item: Resource) => JSON.stringify(item))
  24. }
  25. .scrollBar(BarState.Off)
  26. .columnsTemplate(Constants.GRID_COLUMNS_TEMPLATE)
  27. .rowsGap(Constants.LIST_ITEM_SPACE)
  28. .columnsGap(Constants.LIST_ITEM_SPACE)
  29. .layoutWeight(1)
复制代码


  • 创建一个网格结构 Grid 来展示 photoArr 中的每一张图片。
  • 使用 ForEach 循环遍历 photoArr 数组,为每个图片生成一个 GridItem。
  • 每个 GridItem 包罗一个 Image 组件,用来展示单张图片。设置了图片的高度和宽度为全屏百分比,并使用 objectFit 属性确保图片覆盖整个容器。
  • 当点击某个 GridItem 时,触发 onClick 变乱处理器,更新 selectedIndex 为当前项的索引,并通过路由跳转到详情页 URL_DETAIL_LIST_PAGE,同时传递图片数组作为参数。 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

忿忿的泥巴坨

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表