0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

HarmonyOS开发案例:【电子相册】

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-05-08 09:32 次阅读

介绍

如何实现一个简单的电子相册应用的开发,主要功能包括:

  1. 实现首页顶部的轮播效果。
  2. 实现页面跳转时共享元素的转场动画效果。
  3. 实现通过手势控制图片的放大、缩小、左右滑动查看细节等效果。

相关概念

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

环境搭建

软件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:[润和RK3568开发板]。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. [获取OpenHarmony系统版本]:标准系统解决方案(二进制)。以3.2 Release版本为例:
  2. 搭建烧录环境。
    1. [完成DevEco Device Tool的安装]
    2. [完成RK3568开发板的烧录]
  3. 搭建开发环境。
    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”)。
    3. 工程创建完成后,选择使用[真机进行调测]。
    4. 开发前请熟悉鸿蒙开发指导文档:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。

├──entry/src/main/ets                // 代码区
│  ├──common
│  │  ├──constansts
│  │  │  └──Constants.ets            // 常量类
│  │  └──utils
│  │     └──Logger.ets               // Logger公共类
│  ├──entryability
│  │  └──EntryAbility.ts             // 程序入口类
│  ├──pages
│  │  ├──DetailListPage.ets          // 图片详情页面
│  │  ├──DetailPage.ets              // 查看大图页面
│  │  ├──IndexPage.ets               // 电子相册主页面
│  │  └──ListPage.ets                // 图片列表页面
│  └──view
│     └──PhotoItem.ets               // 首页相册Item组件
└──entry/src/main/resources          // 资源文件

`HarmonyOSOpenHarmony鸿蒙文档籽料:mau123789v直接拿`

搜狗高速浏览器截图20240326151450.png

构建应用页面

应用首页

应用首页用Column组件来实现纵向布局,从上到下依次是标题组件Text、轮播图Swiper、相册列表Grid。标题和轮播图均设置固定高度,底部相册列表通过layoutWeight属性实现自适应占满剩余空间。

// IndexPage.ets
Column() {
  Row() {
    Text($r('app.string.EntryAbility_label'))
  }

  Swiper(this.swiperController) {
    ForEach(Constants.BANNER_IMG_LIST, (item: Resource) = > {
      Row() {
        Image(item)
        ...
      }
    }, (item: Resource, index: number) = > JSON.stringify(item) + index)
  }
  ...

  Grid() {
    ForEach(IMG_ARR, (photoArr: Array< Resource >) = > {
      GridItem() {
        PhotoItem({ photoArr })
      }
      ...
      .onClick(() = > {
        router.pushUrl({
          url: Constants.URL_LIST_PAGE,
          params: { photoArr: JSON.stringify(photoArr) }
        }).catch((error: Error) = > {
          Logger.error(Constants.TAG_INDEX_PAGE, JSON.stringify(error));
        });
      })
    }, (item: Array< Resource >, index: number) = > JSON.stringify(item) + index)
  }
  ...
  .layoutWeight(1)
}

图片列表页面

图片列表页是网格状展开的图片列表,主要使用Grid组件和GridItem组件,GridItem高度通过aspectRatio属性设置为跟宽度一致。

// ListPage.ets
Navigation() {
  Grid() {
    ForEach(this.photoArr, (img: Resource, index: number) = > {
      GridItem() {
        Image(img)
          .onClick(() = > {
            this.selectedIndex = index;
            router.pushUrl({
              url: Constants.URL_DETAIL_LIST_PAGE,
              params: {
                photoArr: JSON.stringify(this.photoArr),
              }
            }).catch((error: Error) = > {
              Logger.error(Constants.TAG_LIST_PAGE, JSON.stringify(error));
            });
          })
      }
      ...
      .aspectRatio(1)
    }, (item: Resource) = > JSON.stringify(item))
  }
  .columnsTemplate(Constants.GRID_COLUMNS_TEMPLATE)
  .layoutWeight(1)
}

图片详情页面

图片详情页由两个横向滚动的List组件完成整体布局,两个组件之间有联动的效果。滚动底部的List,上边展示的图片会随着改变,同样左右滑动上边的图片时,底部List组件也会随之改变。

// DetailListPage.ets
Stack({ alignContent: Alignment.Bottom }) {
  List({ scroller: this.bigScroller, initialIndex: this.selectedIndex }) {
    ForEach(this.photoArr, (img: Resource, index: number) = > {
      ListItem() {
        Image(img)
          ...
          .gesture(PinchGesture({ fingers: Constants.DOUBLE_NUMBER })
            .onActionStart(() = > this.goDetailPage()))
          .onClick(() = > this.goDetailPage())
      }
    }, (item: Resource) = > JSON.stringify(item))
  }
  ...
  .onScroll((scrollOffset, scrollState) = > {
    if (scrollState === ScrollState.Fling) {
      this.bigScrollAction(scrollTypeEnum.SCROLL);
    }
  })
  .onScrollStop(() = > this.bigScrollAction(scrollTypeEnum.STOP))

  List({ scroller: this.smallScroller, space: Constants.LIST_ITEM_SPACE, initialIndex: this.selectedIndex }) {
    ForEach(this.smallPhotoArr, (img: Resource, index: number) = > {
      ListItem() {
        this.SmallImgItemBuilder(img, index)
      }
    }, (item: Resource, index: number) = > JSON.stringify(item) + index)
  }
  ...
  .listDirection(Axis.Horizontal)
  .onScroll((scrollOffset, scrollState) = > {
    if (scrollState === ScrollState.Fling) {
      this.smallScrollAction(scrollTypeEnum.SCROLL);
    }
  })
  .onScrollStop(() = > this.smallScrollAction(scrollTypeEnum.STOP))
}

查看大图页面

查看大图页面由一个横向滚动的List组件来实现图片左右滑动时切换图片的功能,和一个Row组件实现图片的缩放和拖动查看细节功能。对图片进行缩放时会从List组件切换成Row组件来实现对单张图片的操作,对单张图片进行滑动操作时,也会由Row组件转换为List组件来实现图片的切换功能。

// DetailPage.ets
Stack() {
  List({ scroller: this.scroller, initialIndex: this.selectedIndex }) {
    ForEach(this.photoArr, (img: Resource) = > {
      ListItem() {
        Image(img)
          ...
          .onClick(() = > router.back()
          )
      }
      .gesture(PinchGesture({ fingers: Constants.DOUBLE_NUMBER })
        .onActionStart(() = > {
          this.resetImg();
          this.isScaling = true;
          this.imgOffSetX = 0;
          this.imgOffSetY = 0;
        })
        .onActionUpdate((event: GestureEvent) = > {
          this.imgScale = this.currentScale * event.scale;
        })
        .onActionEnd(() = > {
          if (this.imgScale < 1) {
            this.resetImg();
            this.imgOffSetX = 0;
            this.imgOffSetY = 0;
          } else {
            this.currentScale = this.imgScale;
          }
        })
      )
    }, (item: Resource) = > JSON.stringify(item))
  }
  ...
  .onScrollStop(() = > {
    let currentIndex = Math.round((this.scroller.currentOffset()
      .xOffset + (this.imageWidth / Constants.DOUBLE_NUMBER)) / this.imageWidth);
    this.selectedIndex = currentIndex;
    this.scroller.scrollTo({ xOffset: currentIndex * this.imageWidth, yOffset: 0 });
  })
  .visibility(this.isScaling ? Visibility.Hidden : Visibility.Visible)

  Row() {
    Image(this.photoArr[this.selectedIndex])
    ...
  }
  .visibility(this.isScaling ? Visibility.Visible : Visibility.Hidden)
}

通过手势控制图片

大图浏览界面双指捏合时通过改变Image组件的scale来控制图片的缩放,单手拖动时通过改变Image的偏移量来控制图片的位置,手势操作调用组合手势GestureGroup实现。其中PinchGesture实现双指缩放手势,PanGesture实现单指拖动手势。

// DetailPage.ets 
Row() {
    Image(this.photoArr[this.selectedIndex])
      .position({ x: this.imgOffSetX, y: this.imgOffSetY })
      .scale({ x: this.imgScale, y: this.imgScale })
  }
  .gesture(GestureGroup(GestureMode.Exclusive,
  PinchGesture({ fingers: Constants.DOUBLE_NUMBER })
    .onActionUpdate((event: GestureEvent) = > {
      this.imgScale = this.currentScale * event.scale;
    })
    .onActionEnd(() = > {
      if (this.imgScale < 1) {
        this.resetImg();
        this.imgOffSetX = 0;
        this.imgOffSetY = 0;
      } else {
        this.currentScale = this.imgScale;
      }
    }),
  PanGesture()
    .onActionStart(() = > {
      this.preOffsetX = this.imgOffSetX;
      this.preOffsetY = this.imgOffSetY;
    })
    .onActionUpdate((event: GestureEvent) = > {
      this.imgOffSetX = this.preOffsetX + event.offsetX;
      this.imgOffSetY = this.preOffsetY + event.offsetY;
    })
    .onActionEnd(() = > this.handlePanEnd())
  ))

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 鸿蒙
    +关注

    关注

    57

    文章

    2306

    浏览量

    42728
  • OpenHarmony
    +关注

    关注

    25

    文章

    3657

    浏览量

    16127
收藏 人收藏

    评论

    相关推荐

    一个非常不错的电子相册制作工具 MemoriesOnTV

    一个非常不错的电子相册制作工具 MemoriesOnTV该软件上手非常容易,制作的电子相册的过场特效非常专业,现在你还可以要相册中添加视频及文本幻灯,同时增加了相片特效。你不但可以用它来刻录
    发表于 05-14 11:47

    如何制作儿童电子相册?(教程)

    美好记忆保留在脑海中。为了保留宝宝每个瞬间,父母们会给宝宝拍了许许多多的照片,如果这些照片(马伊琍女儿照片)变成了一份精彩的电子相册!连宝宝自己纯真的眼睛看着他的照片在电视上翩翩飞舞,都会不由自主喜欢
    发表于 07-20 12:28

    单片机电子相册DIY

    `单片机电子相册DIY`
    发表于 08-15 22:57

    51单片机2.8寸液晶开发板,运行游戏,电子相册,手写板,...

    资料更新中。。。51单片机液晶开发板,可运行游戏,电子相册,手写板,电子书还可以做测试板用,可以配套2.4寸2.6寸2.8寸3.2寸提供的学习资源有:1,游戏开发(俄罗斯方块,拼图游戏
    发表于 06-10 15:40

    求一个基于frambuffer电子相册制作的源程序?(基于linux高级编程的);

    新手一名,需要一个电子相册的程序,可以播放音乐的,谢了!
    发表于 09-10 10:23

    51单片机TFT2.8 彩屏 -9325ok 电子相册

    `这个压缩包是自己无意在电脑中发现的,看了下,还是挺好。 包括彩色屏显示,触摸,以及使用方式,例程,还有一个电子相册的制作说明。所以上传上来。 觉得有需要的就下载。还有写资料上传不了。。。不知道咋回事。 `
    发表于 04-30 01:29

    基于FATFS文件系统的电子相册

    的图片没有原子的高级11.电子相册.rar (324.46 KB )FATFS浅谈.pdf (248.35 KB )37-文件系统源码(R.007c).rar (1.22 MB )
    发表于 07-16 08:00

    ARM裸机开发之基于Mini2451开发板的电子相册开发步骤

    该项目的制作是用的友善之臂的Mini2451开发板。简单先介绍一下该电子相册的主要功能即操作:开发板上一共有4个按键,K1是进入选择界面,选择界面中K2为手动切换,K3为自动切换,在自动切换模式中
    发表于 05-19 14:36

    HarmonyOS做一个可以手势控制的电子相册应用(ArkTS)

    介绍 本篇Codelab介绍了如何实现一个简单的电子相册应用,主要功能包括: 实现首页顶部的轮播效果。 实现页面多种布局方式。 实现通过手势控制图片的放大、缩小、左右滑动查看细节等效果。 相关概念
    发表于 10-23 14:14

    【迪文COF结构智能屏试用体验】基于串口通信的电子相册(动态平滑、完整代码)

    分享。 这篇分享,涉及或需要了解下面的知识: 迪文COF智能屏基础了解 运行时内存中数据存储的原理 迪文DBUS GUI开发软件 串口指令的基本使用 串口传送图片数据的原理 电子相册的原理 Python
    发表于 12-06 15:58

    JAVA教程之电子相册

    JAVA教程之电子相册,很好的JAVA的资料,快来学习吧
    发表于 04-11 17:14 5次下载

    基于Web电子相册3D翻页效果实现

    随着科技的不断进步,在个人用户体验的操作系统中已包含了众多图形算法和桌面渲染。随着3D技术的发展,人们越来越倾向于基于Web的3D真实感体验,研究人员目前正在大力研究这个问题。电子相册制作
    发表于 11-16 09:24 6次下载
    基于Web<b class='flag-5'>电子相册</b>3D翻页效果实现

    视频电子相册制作中视频不清晰的原因和办法

    用户在使用艾奇电子相册制作软件的时候,可能会遇到制作出的视频播放不清晰的情况。艾奇KTV电子相册视频制作软件,为了强化输出质量,默认的输出分辨率是比较高的。所以默认参数下制作输出的视频文件会比较大,同时清晰度也会高。
    发表于 08-08 16:19 5317次阅读

    华为开发者分论坛HarmonyOS学生公开课-OpenHarmony Codelabs开发案

    2021华为开发者分论坛HarmonyOS学生公开课-OpenHarmony Codelabs开发案
    的头像 发表于 10-24 11:25 1881次阅读
    华为<b class='flag-5'>开发</b>者分论坛<b class='flag-5'>HarmonyOS</b>学生公开课-OpenHarmony Codelabs<b class='flag-5'>开发案</b>例

    基于Java Web电子相册

    基于Java web的电子相册系统
    发表于 06-26 15:25 0次下载