回复
     06-自然壁纸实战教程-壁纸下载 原创
万少skr
 发布于 2025-7-8 14:49
 浏览
 0收藏
06-自然壁纸实战教程-壁纸下载
前言
当用户在浏览壁纸时,点击壁纸,便进入到详情页面,详情页面提供了壁纸下载的功能,这里主要就是讲解壁纸下载的实现过程

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

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

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进行路由管理的,所以不懂怎么使用的小伙伴需要先学习下。
壁纸详情

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

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

申请壁纸下载权限
这里申请壁纸下载权限使用的是鸿蒙提供的安全按钮 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);
      }
    });
  });
};
- 函数接受一个参数 
url,表示要请求的URL。 - 返回一个Promise对象,该Promise对象在请求成功时解析为HTTP响应,否则拒绝并返回错误。
 - 使用 
http.createHttp()创建一个HTTP客户端实例。 - 调用 
request方法发送HTTP GET请求到指定的URL,并设置请求的超时时间为60秒。 - 在请求的回调函数中,检查是否有错误发生:
- 如果有错误,调用 
reject函数,将错误传递给Promise的拒绝处理程序。 - 如果没有错误,调用 
resolve函数,将HTTP响应传递给Promise的解析处理程序。 
 - 如果有错误,调用 
 
保存到相册
核心代码是利用了 image 和  photoAccessHelper kit。
主要逻辑:
- 定义响应码常量和图片打包选项。
 - 使用
httpRequest函数发起HTTP请求,获取图片数据。 - 检查HTTP响应码是否为成功(
responseCode.OK),如果是,则继续处理。 - 将获取到的图片数据转换为
ImageSource对象。 - 定义图片处理选项,包括图片大小、透明度、是否可编辑、像素格式和缩略值。
 - 使用
ImageSource对象创建PixelMap对象,该对象表示图片的像素数据。 - 使用
ImagePacker对象将PixelMap对象打包为数据。 - 获取上下文并创建照片访问助手,用于访问设备的照片库。
 - 使用照片访问助手创建一个新的图片文件,并获取其URI。
 - 打开文件并写入打包后的数据。
 - 关闭文件,释放
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();
  }
}
如何获取资料
获取资料的途径,可以关注我们 官网的公众号 青蓝逐码 ,输入 项目名称 《自然壁纸》 即可获得以上资料。
关于我们
如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯,甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。

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



















