06-自然壁纸实战教程-壁纸下载 原创

万少skr
发布于 2025-7-8 14:49
浏览
0收藏

06-自然壁纸实战教程-壁纸下载

前言

当用户在浏览壁纸时,点击壁纸,便进入到详情页面,详情页面提供了壁纸下载的功能,这里主要就是讲解壁纸下载的实现过程

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

壁纸组件

这里的壁纸渲染是封装了一个自定义组件来实现的

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

WallpaperCard 组件内,封装了个骨架屏组件,当图片还没有加载出来时,就优先显示骨架屏。

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

import { NavigationConst } from "../const/NavigationConst"
import { NavigationUtils } from "../utils/NavigationUtils"
import { PixabayImage } from "../utils/types"
import { IvSkeleton } from "./IvSkeleton"

// 壁纸卡片组件
@ComponentV2
export struct WallpaperCard {
  @Param @Require image: PixabayImage
  // 图片加载状态
  @Local isLoading: boolean = true

  build() {
    Column() {
      Image(this.image.webformatURL)
        .width('100%')
        .height(300)
        .borderRadius(10)
        .visibility(this.isLoading ? Visibility.Hidden : Visibility.Visible)
        .onComplete(() => {
          // 图片加载完成
          this.isLoading = false
        })
        .onClick(() => {
          // 打开图片详情
          NavigationUtils.getInstance().navigatePush(NavigationConst.ImageDetail_View, this.image)
        })
      // 骨架屏占位
      if (this.isLoading) {
        IvSkeleton({ widthValue: '100%', heightValue: 300 })
          .borderRadius(10)
          .position({ x: 0, y: 0 })
      }
    }
    .width('100%')
  }
}

点击跳转到壁纸详情

当点击壁纸时,便跳转到壁纸详情页面

NavigationUtils.getInstance().navigatePush(NavigationConst.ImageDetail_View, this.image)

这里的跳转是使用了Navigation进行路由管理的,所以不懂怎么使用的小伙伴需要先学习下。

壁纸详情

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

壁纸详情的布局挺简单,上到下直接布局即可。

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

下载壁纸

核心业务在于 下载壁纸,这里的下载壁纸分成三个核心步骤,分别是 申请壁纸下载权限下载壁纸保存到相册

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

申请壁纸下载权限

这里申请壁纸下载权限使用的是鸿蒙提供的安全按钮 SaveButton,安全控件的保存控件。用户点击保存控件,应用可以临时获取存储权限,而不需要权限弹框授权确认。

SaveButton属性

名称 类型 必填 说明
icon SaveIconStyle 设置保存控件的图标风格。不传入该参数表示没有图标。
text SaveDescription 设置保存控件的文本描述。不传入该参数表示没有文字描述。
buttonType ButtonType 设置保存控件的背景样式。不传入该参数,系统默认提供Capsule类型按钮。

开始下载图片

loadImageWithUrl 自己封装的方法用来下载对应的图片

SaveButton(
  {
    text: SaveDescription.SAVE_IMAGE
  }
)
  .width(120)
  .height(40)
  .backgroundColor($r('sys.color.brand'))
  .borderRadius(20)
  .fontColor($r('sys.color.comp_background_list_card'))
  .onClick(async () => {
    await loadImageWithUrl(this.selectedImage!.largeImageURL)
    promptAction.showToast({ message: `下载成功` })
  })

下载图片主要使用 http模块来实现

// 将 http 请求封装为返回 Promise 的函数
const httpRequest = (url: string) => {
  return new Promise<http.HttpResponse>((resolve, reject) => {
    http.createHttp().request(url, {
      method: http.RequestMethod.GET,
      connectTimeout: 60000,
      readTimeout: 60000
    }, (error: BusinessError, data: http.HttpResponse) => {
      if (error) {
        reject(error);
      } else {
        resolve(data);
      }
    });
  });
};
  1. 函数接受一个参数 url,表示要请求的URL。
  2. 返回一个Promise对象,该Promise对象在请求成功时解析为HTTP响应,否则拒绝并返回错误。
  3. 使用 http.createHttp() 创建一个HTTP客户端实例。
  4. 调用 request 方法发送HTTP GET请求到指定的URL,并设置请求的超时时间为60秒。
  5. 在请求的回调函数中,检查是否有错误发生:
    • 如果有错误,调用 reject 函数,将错误传递给Promise的拒绝处理程序。
    • 如果没有错误,调用 resolve 函数,将HTTP响应传递给Promise的解析处理程序。

保存到相册

核心代码是利用了 imagephotoAccessHelper kit。

主要逻辑:

  1. 定义响应码常量和图片打包选项。
  2. 使用httpRequest函数发起HTTP请求,获取图片数据。
  3. 检查HTTP响应码是否为成功(responseCode.OK),如果是,则继续处理。
  4. 将获取到的图片数据转换为ImageSource对象。
  5. 定义图片处理选项,包括图片大小、透明度、是否可编辑、像素格式和缩略值。
  6. 使用ImageSource对象创建PixelMap对象,该对象表示图片的像素数据。
  7. 使用ImagePacker对象将PixelMap对象打包为数据。
  8. 获取上下文并创建照片访问助手,用于访问设备的照片库。
  9. 使用照片访问助手创建一个新的图片文件,并获取其URI。
  10. 打开文件并写入打包后的数据。
  11. 关闭文件,释放PixelMap对象。
export const loadImageWithUrl = async (url: string) => {
  let responseCode = http.ResponseCode;
  let imagePackerApi = image.createImagePacker();
  let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 98 };
  // 发起 http 请求
  const OutData = await httpRequest(url);
  let code: http.ResponseCode | number = OutData.responseCode;

  if (responseCode.OK === code) {
    let imageData: ArrayBuffer = OutData.result as ArrayBuffer;
    let imageSource: image.ImageSource = image.createImageSource(imageData);

    class tmp {
      height: number = 100;
      width: number = 100;
    }

    let options: Record<string, number | boolean | tmp> = {
      'alphaType': 0, // 透明度
      'editable': false, // 是否可编辑
      'pixelFormat': 3, // 像素格式
      'scaleMode': 1, // 缩略值
      'size': { height: 100, width: 100 }
    }; // 创建图片大小

    // 创建像素图
    const pixelMap: PixelMap = await imageSource.createPixelMap(options);
    // 打包像素图为数据
    const buffer = await imagePackerApi.packToData(pixelMap, packOpts);
    const context = getContext();
    let helper = photoAccessHelper.getPhotoAccessHelper(context);
    let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'png');
    let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
    // 写入文件
    await fileIo.write(file.fd, buffer);
    // 关闭文件
    await fileIo.close(file.fd);
    // 释放像素图
    pixelMap.release();
  }
}

如何获取资料

获取资料的途径,可以关注我们 官网的公众号 青蓝逐码 ,输入 项目名称 《自然壁纸》 即可获得以上资料。

关于我们

关于青蓝逐码组织

如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。

06-自然壁纸实战教程-壁纸下载-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
收藏
回复
举报
回复
    相关推荐