当前位置: 首页 > news >正文

ArkUI(轮播图,图片)组件介绍

Swiper组件提供滑动轮播显示的能力。Swiper本身是一个容器组件,当设置了多个子组件后,可以对这些子组件进行轮播显示。通常,在一些应用首页显示推荐的内容时,需要用到轮播显示的能力。

针对复杂页面场景,可以使用Swiper组件的预加载机制,利用主线程的空闲时间来提前构建和布局绘制组件,优化滑动体验。

布局与约束

Swiper作为一个容器组件,如果设置了自身尺寸属性,则在轮播显示过程中均以该尺寸生效。如果自身尺寸属性未被设置,则分两种情况:如果设置了prevMargin或者nextMargin属性,则Swiper自身尺寸会跟随其父组件;如果未设置prevMargin或者nextMargin属性,则会自动根据子组件的大小设置自身的尺寸。

循环播放

通过loop属性控制是否循环播放,该属性默认值为true。

当loop为true时,在显示第一页或最后一页时,可以继续往前切换到前一页或者往后切换到后一页。如果loop为false,则在第一页或最后一页时,无法继续向前或者向后切换页面。

  • loop为true
  1. Swiper() {
  2. Text('0')
  3. .width('90%')
  4. .height('100%')
  5. .backgroundColor(Color.Gray)
  6. .textAlign(TextAlign.Center)
  7. .fontSize(30)
  8. Text('1')
  9. .width('90%')
  10. .height('100%')
  11. .backgroundColor(Color.Green)
  12. .textAlign(TextAlign.Center)
  13. .fontSize(30)
  14. Text('2')
  15. .width('90%')
  16. .height('100%')
  17. .backgroundColor(Color.Pink)
  18. .textAlign(TextAlign.Center)
  19. .fontSize(30)
  20. }
  21. // ···
  22. .loop(true)

SwiperLoop.ets

  • loop为false
  1. Swiper() {
  2. // ···
  3. }
  4. // ···
  5. .loop(false)

SwiperLoop.ets

自动轮播

Swiper通过设置autoPlay属性,控制是否自动轮播子组件。该属性默认值为false。

autoPlay为true时,会自动切换播放子组件,子组件与子组件之间的播放间隔通过interval属性设置。interval属性默认值为3000,单位毫秒。

  1. Swiper() {
  2. // ···
  3. }
  4. // ···
  5. .loop(true)
  6. .autoPlay(true)
  7. .interval(1000)

SwiperAutoPlay.ets

页面切换方式

Swiper支持手指滑动、点击导航点和通过控制器三种方式切换页面,以下示例展示通过控制器切换页面的方法。

  1. // 如需作为页面入口,请取消@Entry的注释并删除export关键字
  2. // @Entry
  3. @Component
  4. export struct SwiperPageSwitchMethod {
  5. private swiperBackgroundColors: Color[] = [Color.Blue, Color.Brown, Color.Gray, Color.Green, Color.Orange,
  6. Color.Pink, Color.Red, Color.Yellow];
  7. private swiperAnimationMode: (SwiperAnimationMode | boolean | undefined)[] = [undefined, true, false,
  8. SwiperAnimationMode.NO_ANIMATION, SwiperAnimationMode.DEFAULT_ANIMATION, SwiperAnimationMode.FAST_ANIMATION];
  9. private swiperController: SwiperController = new SwiperController();
  10. private animationModeIndex: number = 0;
  11. private animationMode: (SwiperAnimationMode | boolean | undefined) = undefined;
  12. @State animationModeStr: string = 'undefined';
  13. @State targetIndex: number = 0;
  14. aboutToAppear(): void {
  15. this.toSwiperAnimationModeStr();
  16. }
  17. build() {
  18. // ...
  19. Column({ space: 5 }) {
  20. Swiper(this.swiperController) {
  21. ForEach(this.swiperBackgroundColors, (backgroundColor: Color, index: number) => {
  22. Text(index.toString())
  23. .width(250)
  24. .height(250)
  25. .backgroundColor(backgroundColor)
  26. .textAlign(TextAlign.Center)
  27. .fontSize(30)
  28. })
  29. }
  30. // ...
  31. .indicator(true)
  32. Row({ space: 12 }) {
  33. Button('showNext')
  34. .onClick(() => {
  35. this.swiperController.showNext(); // 通过controller切换到后一页
  36. })
  37. Button('showPrevious')
  38. .onClick(() => {
  39. this.swiperController.showPrevious(); // 通过controller切换到前一页
  40. })
  41. }.margin(5)
  42. Row({ space: 12 }) {
  43. Text('Index:')
  44. Button(this.targetIndex.toString())
  45. .onClick(() => {
  46. this.targetIndex = (this.targetIndex + 1) % this.swiperBackgroundColors.length;
  47. })
  48. }.margin(5)
  49. Row({ space: 12 }) {
  50. Text('AnimationMode:')
  51. Button(this.animationModeStr)
  52. .onClick(() => {
  53. this.animationModeIndex = (this.animationModeIndex + 1) % this.swiperAnimationMode.length;
  54. this.toSwiperAnimationModeStr();
  55. })
  56. }.margin(5)
  57. Row({ space: 12 }) {
  58. Button('changeIndex(' + this.targetIndex + ', ' + this.animationModeStr + ')')
  59. .onClick(() => {
  60. this.swiperController.changeIndex(this.targetIndex, this.animationMode); // 通过controller切换到指定页
  61. })
  62. }.margin(5)
  63. }
  64. // ...
  65. }
  66. private toSwiperAnimationModeStr() {
  67. this.animationMode = this.swiperAnimationMode[this.animationModeIndex];
  68. if ((this.animationMode === true) || (this.animationMode === false)) {
  69. this.animationModeStr = '' + this.animationMode;
  70. } else if ((this.animationMode === SwiperAnimationMode.NO_ANIMATION) ||
  71. (this.animationMode === SwiperAnimationMode.DEFAULT_ANIMATION) ||
  72. (this.animationMode === SwiperAnimationMode.FAST_ANIMATION)) {
  73. this.animationModeStr = SwiperAnimationMode[this.animationMode];
  74. } else {
  75. this.animationModeStr = 'undefined';
  76. }
  77. }
  78. }

SwiperPageSwitchMethod.ets

开发者经常需要在应用中显示一些图片,例如:按钮中的icon、网络图片、本地图片等。在应用中显示图片需要使用Image组件实现,Image支持多种图片格式,包括png、jpg、jpeg等格式,不支持apng和svga格式,具体支持格式和用法请参考Image组件。

Image通过调用接口来创建,接口调用形式如下:

  1. Image(src: PixelMap | ResourceStr | DrawableDescriptor)

该接口通过图片数据源获取图片,支持本地图片和网络图片的渲染展示。其中,src是图片的数据源,加载方式请参考加载图片资源。

如果图片加载过程中出现白色块,请参考Image白块解决方案。如果图片加载时间过长,请参考预置图片资源加载优化。

加载图片资源

Image支持加载存档图、多媒体像素图和可绘制描述符三种类型。

存档图类型数据源

存档图类型的数据源可以分为本地资源、网络资源、Resource资源、媒体库资源和base64。

  • 本地资源

    创建文件夹,将本地图片放入ets文件夹下的任意位置。

    Image组件引入本地图片路径,即可显示图片(根目录为ets文件夹)。不支持跨包、跨模块调用该Image组件。

    说明

    从DevEco Studio 6.0.0 Beta2版本开始,新建工程或模块时,默认创建的模块不会对非resources目录下的资源进行打包,需使相关模块:build-profile.json5中buildOption > resOptions > copyCodeResource > enable设置为true,详见resOptions中copyCodeResource相关介绍。

    1. // 'images/view.jpg'需要替换为开发者所需的资源文件
    2. Image('images/view.jpg')
    3. .width(200)

    LoadingResources.ets

    加载本地图片过程中,如果对图片进行修改或者替换,可能会引起应用崩溃。因此需要覆盖图片文件时,应该先删除该文件再重新创建一个同名文件。

  • 网络资源

    引入网络图片需申请权限ohos.permission.INTERNET,具体申请方式请参考声明权限。此时,Image组件的src参数为网络图片的链接。

    当前Image组件仅支持加载简单网络图片。

    首次加载网络图片时,Image组件需要请求网络资源;非首次加载时,默认从缓存中直接读取图片。

    更多图片缓存设置请参考setImageCacheCount、setImageRawDataCacheSize和setImageFileCacheSize。这三个图片缓存接口主要用于支持简单、通用的场景,后续不再继续演进,且在灵活和扩展性方面存在一定限制,例如:

    • 无法获取当前缓存占用信息。Image组件目前不支持查询磁盘缓存的实时状态,包括文件总大小和文件数量。
    • 缓存策略不可定制,缺乏缓存状态观测能力。开发者无法通过接口感知缓存命中率、淘汰次数等运行时的指标,难以基于实际缓存效果进行动态调优。

    对于复杂情况,推荐使用ImageKnife,该图像库提供了更灵活、可扩展的缓存策略以及完善的生命周期管理能力,更适合复杂业务需求。

    网络图片必须支持RFC 9113标准,否则会导致加载失败。如果下载的网络图片大于10MB或一次下载的网络图片数量较多,建议使用HTTP工具提前下载,提高图片加载性能,方便应用侧管理数据。

    在显示网络图片时,Image组件在机制上会依赖缓存下载模块,开发者可参考示例3(下载与显示网络gif图片)了解具体用法。

    缓存下载模块提供独立的预下载接口,允许应用开发者在创建Image组件前预下载所需图片。组件创建后,Image组件可直接从缓存下载模块中获取已下载的图片数据,从而加快图片的显示速度,优化加载体验,并有效避免网络图片加载延迟。网络缓存的位置位于应用根目录下的cache目录中。

    1. // $r('app.string.LoadingResources')需要替换为开发者所需的资源文件,资源文件中的value值请替换为真实路径
    2. Image($r('app.string.LoadingResources'))

    LoadingResources.ets

  • Resource资源

    使用资源格式可以跨包/跨模块引入图片,resources文件夹下的图片都可以通过$r资源接口读取到并转换到Resource格式。

    图1resources

    调用方式:

    1. // 请将$r('app.media.icon')替换为实际资源文件
    2. Image($r('app.media.icon'))

    LoadingResources.ets

    还可以将图片放在rawfile文件夹下。

    图2rawfile

    调用方式:

    1. // $rawfile('example1.png')需要替换为开发者所需的资源文件
    2. Image($rawfile('example1.png'))

    LoadingResources.ets

  • 媒体库file://data/storage

    支持file://路径前缀的字符串,用于访问通过选择器提供的图片路径。

    1. 调用接口获取图库的照片url。
      1. import { photoAccessHelper } from '@kit.MediaLibraryKit';
      2. import { BusinessError } from '@kit.BasicServicesKit';
      3. import { hilog } from '@kit.PerformanceAnalysisKit';
      4. const DOMAIN = 0x0001;
      5. const TAG = 'Sample_imagecomponent';
      6. @Entry
      7. @Component
      8. struct MediaLibraryFile {
      9. @State imgDatas: string[] = [];
      10. // 使用PhotoViewPicker唤起图片选择器,选择图片并且渲染到页面中
      11. // 获取照片url集
      12. getAllImg() {
      13. try {
      14. let photoSelectOptions:photoAccessHelper.PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
      15. photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
      16. photoSelectOptions.maxSelectNumber = 5;
      17. let photoPicker:photoAccessHelper.PhotoViewPicker = new photoAccessHelper.PhotoViewPicker();
      18. photoPicker.select(photoSelectOptions).then((photoSelectResult:photoAccessHelper.PhotoSelectResult) => {
      19. this.imgDatas = photoSelectResult.photoUris;
      20. hilog.info(DOMAIN, TAG,'PhotoViewPicker.select successfully, photoSelectResult uri: ' + JSON.stringify(photoSelectResult));
      21. }).catch((err:Error) => {
      22. let message = (err as BusinessError).message;
      23. let code = (err as BusinessError).code;
      24. hilog.info(DOMAIN, TAG,`PhotoViewPicker.select failed with. Code: ${code}, message: ${message}`);
      25. });
      26. } catch (err) {
      27. let message = (err as BusinessError).message;
      28. let code = (err as BusinessError).code;
      29. hilog.info(DOMAIN, TAG,`PhotoViewPicker failed with. Code: ${code}, message: ${message}`);
      30. };
      31. };
      32. // aboutToAppear中调用上述函数,获取图库的所有图片url,存在imgDatas中
      33. async aboutToAppear() {
      34. this.getAllImg();
      35. };
      36. // 使用imgDatas的url加载图片
      37. build() {
      38. Column() {
      39. Grid() {
      40. ForEach(this.imgDatas, (item:string) => {
      41. GridItem() {
      42. Image(item)
      43. .width(200)
      44. }
      45. }, (item:string):string => JSON.stringify(item))
      46. }
      47. }.width('100%').height('100%')
      48. }
      49. }

      LoadImageResources.ets

    2. 从媒体库获取的url格式通常如下。
      1. // 'file://media/Photos/5'需要替换为开发者所需的资源文件,资源文件中的value值请替换为真实路径
      2. Image('file://media/Photos/5')
      3. .width(200)

以上内容均参考于显示图片 (Image)-媒体展示-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

创建轮播 (Swiper)-媒体展示-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

实战演示

http://www.jsqmd.com/news/1084303/

相关文章:

  • 2026无水印在线抠图教程!无需下载AI在线抠图,一键生成高清透明底图片
  • 从YOLOv5部署实践,深入理解智能计算系统分层架构与优化
  • DevCloud 预置镜像避坑指南与 ROCm 版本锁定
  • 跨平台绘图新选择:如何用免费工具彻底告别Visio依赖
  • Windows系统文件d3dx9_41.dll丢失找不到问题解决
  • 9大网盘直链下载助手完整指南:一键获取真实下载地址,告别限速烦恼
  • 伴随诊断抗体如何实现精准医疗的技术突破?
  • 京东智能评价终极指南:5分钟实现自动化评价管理
  • 短信平台的数据监控架构设计
  • 2026年全链路性能测试:从场景仿真到平台化构建的实战指南
  • JL-34 超声波一体式气象站 轻松搞定多要素环境监测
  • 低成本单相电计量方案:HLW8032+ESP32实现
  • 在windows平台上,dbghlp和ASAN两种方式定位崩溃问题
  • [特殊字符] 刷爆前端圈!Qwythos-9B 震撼发布:4GB 显存畅玩 104 万超长上下文,真“无审查”平替 Claude?
  • 2026AI抠图工具保姆级教程:免费在线+电脑端+手机端全覆盖,新手零失败
  • Blender UV编辑终极指南:UvSquares插件让复杂网格一键变规整
  • 告别文字墙!TokUI让AI渲染像刷短视频一样丝滑
  • 编写 Python 脚本快速诊断 AMD GPU 健康状态
  • 口碑超棒!这家电动无轨龙门架制造厂家究竟有何过人之处?
  • 蛋仔网:独立游戏资源网站怎么选,授权和来源先看清
  • 告别重复编码!用Live Templates将日志/DTO/Controller生成速度提升300%(实测数据)
  • Unity基础:认识Unity引擎——从游戏引擎概念到Unity发展历程
  • vLLM 在 ROCm 7.x 下的显存参数精细调优实战
  • SillyTavern架构演进:3种战略迁移方案与技术评估指南
  • RAG 检索方式全解析:关键词、向量、混合检索与 Rerank
  • Linux嵌入式x86/ARM中的Bootloader基本概念与启动流程解析
  • 40 英镑的 Xteink X4 电子墨水阅读器:小巧便携,自定义固件让阅读体验升级!
  • 网约车拼车系统新范式:效率与公平的动态平衡算法解析
  • 终极AMD Ryzen处理器调试指南:硬件性能调优与系统监控完整教程
  • 解决 vLLM 在 AMD 平台上的编译报错与依赖冲突