【HarmonyOS Next】图片选择方案

打印 上一主题 下一主题

主题 852|帖子 852|积分 2556

配景


封装一个选择图片和调用照相相机的按钮,展示api13下选择图片和调用相机,可以使用不申请用户权限的方式,举行图片的选择和修改。但是,目前方案并未包罗上传图片生存的功能,仅提供图片选择或者照相后,图片展示的一种方案。

项目架构




  • Common :公共操作类存放文件夹
  • PromptActionClass:全局弹窗操作类
  • components:公共弹窗组件文件夹
  • SelectImageDialog:选择图片弹窗组件
  • pages->Index:入口界面
紧张方法解析


调用相机照相



  • 添加camera, cameraPicker的外部引用
  1. import { camera, cameraPicker } from '@kit.CameraKit';
复制代码


  • 使用cameraPicker的pick方法实现安全调用设备相机,并返回选择结果cameraPicker.PickerResult对象,通过设置cameraPicker.PickerProfile对象属性实现对相机的初始化属性设置。
  1. try {
  2.   //配置相机设置
  3.   let pickerProfile: cameraPicker.PickerProfile = {
  4.     cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK,
  5.   };
  6.   let result: cameraPicker.PickerResult =
  7.     await cameraPicker.pick(getContext(), [cameraPicker.PickerMediaType.PHOTO],
  8.       pickerProfile);
  9.   if (result.resultCode == 0) {
  10.     await this.UpdateShowImage(result.resultUri);
  11.   }
  12.   PromptActionClass.CloseDialog();
  13.   return true;
  14. } catch (e) {
  15.   console.info(e);
  16.   return false;
  17. }
复制代码
访问图库选择图片



  • 添加PromptActionClass的外部引用
  1. import { PromptActionClass } from '../Common/PromptActionClass';
复制代码


  • 使用photoAccessHelper.PhotoViewPicker对象的select方法,实现安全调用相册并选择图片。通过photoAccessHelper.PhotoSelectOptions对象,对选择方法举行初始化,可以设置默认选择、选择数量、选择范例等。
  1. try {
  2.   const photoSelectOpt = new photoAccessHelper.PhotoSelectOptions();
  3.   //设置选择类型
  4.   photoSelectOpt.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
  5.   //选择图片最大数量
  6.   photoSelectOpt.maxSelectNumber = 1;
  7.   //图片选择器
  8.   const photoPicker = new photoAccessHelper.PhotoViewPicker();
  9.   const selectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(photoSelectOpt)
  10.   let uri: string = "";
  11.   if (selectResult.isOriginalPhoto || selectResult.photoUris.length == 0) {
  12.     return false;
  13.   }
  14.   uri = selectResult.photoUris[0];
  15.   await this.UpdateShowImage(uri);
  16.   PromptActionClass.CloseDialog();
  17.   return true;
  18. } catch (e) {
  19.   console.info(e);
  20.   return false;
  21. }
复制代码
整体代码


Index

  1. import { image } from '@kit.ImageKit';import { photoAccessHelper } from '@kit.MediaLibraryKit';import { fileIo } from '@kit.CoreFileKit';import { PromptActionClass } from '../Common/PromptActionClass';
  2. import { SelectImageDialog } from '../components/SelectImageDialog';import { camera, cameraPicker } from '@kit.CameraKit';
  3. @Entry@ComponentV2struct Index {  @Local ShowImage: ResourceStr | PixelMap = $r('app.media.AddImageIcon')  aboutToAppear(): void {    PromptActionClass.SetContext(this.getUIContext());    PromptActionClass.SetOptions({      builder: () => {        this.PictureBuilder()      },      alignment: DialogAlignment.Bottom,      cornerRadius: {        topLeft: 20,        topRight: 20,        bottomLeft: 20,        bottomRight: 20      },      height: 154,      width: "90%",    })  }  build() {    RelativeContainer() {      Button() {        Image(this.ShowImage)          .width("100%")          .borderRadius(20)          .padding(10)      }      .width(120)      .height(120)      .type(ButtonType.Normal)      .backgroundColor(Color.White)      .borderWidth(3)      .borderColor('#592708')      .borderRadius(20)      .id("AddImageBtn")      .alignRules({        middle: { anchor: "__container__", align: HorizontalAlign.Center }      })      .margin({ top: 20 })      .onClick(() => {        PromptActionClass.OpenDialog();      })    }    .height('100%')    .width('100%')  }  @Builder  PictureBuilder() {    SelectImageDialog({      CancelEvent: async () => {        try {          PromptActionClass.CloseDialog();          return true;        } catch (e) {          console.info(e);          return false;        }      },      TakePictureEvent: async () => {        try {          //设置相机设置          let pickerProfile: cameraPicker.PickerProfile = {            cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK,          };          let result: cameraPicker.PickerResult =            await cameraPicker.pick(getContext(), [cameraPicker.PickerMediaType.PHOTO],              pickerProfile);          if (result.resultCode == 0) {            await this.UpdateShowImage(result.resultUri);          }          PromptActionClass.CloseDialog();          return true;        } catch (e) {          console.info(e);          return false;        }      },      SelectedPictureEvent: async () => {        try {          const photoSelectOpt = new photoAccessHelper.PhotoSelectOptions();          //设置选择范例          photoSelectOpt.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;          //选择图片最大数量          photoSelectOpt.maxSelectNumber = 1;          //图片选择器          const photoPicker = new photoAccessHelper.PhotoViewPicker();          const selectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(photoSelectOpt)          let uri: string = "";          if (selectResult.isOriginalPhoto || selectResult.photoUris.length == 0) {            return false;          }          uri = selectResult.photoUris[0];          await this.UpdateShowImage(uri);          PromptActionClass.CloseDialog();          return true;        } catch (e) {          console.info(e);          return false;        }      }    })  }  async UpdateShowImage(uri: string) {    let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)    const imageSourceApi = image.createImageSource(file.fd);    let map: PixelMap = await imageSourceApi.createPixelMap();    this.ShowImage = map;  }}
复制代码
PromptActionClass

  1. import { promptAction } from "@kit.ArkUI";
  2. import { BusinessError } from "@kit.BasicServicesKit";
  3. /**
  4. * 弹窗操作类
  5. */
  6. export class PromptActionClass {
  7.   /**
  8.    *展示界面的ID集合
  9.    */
  10.   private static ShowIDArray: number[] = [];
  11.   static Context: UIContext;
  12.   /**
  13.    * 弹窗界面设置
  14.    */
  15.   static Options: promptAction.CustomDialogOptions;
  16.   static SetContext(context: UIContext) {
  17.     PromptActionClass.Context = context;
  18.   }
  19.   static SetOptions(options: promptAction.CustomDialogOptions) {
  20.     PromptActionClass.Options = options;
  21.   }
  22.   /**
  23.    * 弹窗
  24.    */
  25.   static OpenDialog() {
  26.     if (PromptActionClass.Options) {
  27.       PromptActionClass.Context.getPromptAction()
  28.         .openCustomDialog(PromptActionClass.Options)
  29.         .then((id: number) => {
  30.           PromptActionClass.ShowIDArray.push(id);
  31.           console.info('弹窗已打开')
  32.         })
  33.         .catch((error: BusinessError) => {
  34.           let message = (error as BusinessError).message;
  35.           let code = (error as BusinessError).code;
  36.           console.error(`弹窗失败,错误代码是:${code}, message 是 ${message}`);
  37.         })
  38.     }
  39.   }
  40.   /**
  41.    * 关闭弹窗
  42.    */
  43.   static CloseDialog() {
  44.     if (PromptActionClass.ShowIDArray.length != 0) {
  45.       try {
  46.         PromptActionClass.Context.getPromptAction()
  47.           .closeCustomDialog(PromptActionClass.ShowIDArray[PromptActionClass.ShowIDArray.length-1])
  48.         console.info('成功关闭弹窗.')
  49.       } catch {
  50.         (error: BusinessError) => {
  51.           let message = (error as BusinessError).message;
  52.           let code = (error as BusinessError).code;
  53.           console.error(`弹窗关闭失败,错误代码:${code}, message 是 ${message}`);
  54.         }
  55.       }
  56.     }
  57.   }
  58. }
复制代码
SelectImageDialog

  1. @ComponentV2
  2. export struct SelectImageDialog {
  3.   @Event TakePictureEvent: () => Promise<boolean> = async () => {
  4.     return false;
  5.   }
  6.   @Event SelectedPictureEvent: () => Promise<boolean> = async () => {
  7.     return false;
  8.   }
  9.   @Event CancelEvent: () => Promise<boolean> = async () => {
  10.     return false;
  11.   }
  12.   build() {
  13.     RelativeContainer() {
  14.       Button("拍照")
  15.         .type(ButtonType.Normal)
  16.         .width("100%")
  17.         .id("TakePictureBtn")
  18.         .backgroundColor("#ffffff")
  19.         .height(50)
  20.         .fontColor("#343434")
  21.         .alignRules({
  22.           bottom: { anchor: "SelectedPictureBtn", align: VerticalAlign.Top }
  23.         })
  24.         .onClick(async () => {
  25.           await this.TakePictureEvent();
  26.         })
  27.       Button("从相册中选择")
  28.         .type(ButtonType.Normal)
  29.         .width("100%")
  30.         .height(50)
  31.         .id("SelectedPictureBtn")
  32.         .backgroundColor("#ffffff")
  33.         .fontColor("#343434")
  34.         .borderWidth({ bottom: 2, top: 2 })
  35.         .borderColor("#f6f6f6")
  36.         .alignRules({
  37.           center: { anchor: "__container__", align: VerticalAlign.Center }
  38.         })
  39.         .onClick(async () => {
  40.           await this.SelectedPictureEvent();
  41.         })
  42.       Button("取消")
  43.         .width("100%")
  44.         .type(ButtonType.Normal)
  45.         .height(50)
  46.         .backgroundColor("#ffffff")
  47.         .fontColor("#aeaeae")
  48.         .alignRules({
  49.           top: { anchor: "SelectedPictureBtn", align: VerticalAlign.Bottom }
  50.         })
  51.         .onClick(async () => {
  52.           await this.CancelEvent();
  53.         })
  54.     }
  55.     .height("100%")
  56.     .width("100%")
  57.   }
  58. }
复制代码
图片资源

从绑定资源中下载
代码文件下载

ImageSelectDemo: 图片选择博客代码

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

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

何小豆儿在此

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表