鴻蒙HarmonyOS App開發造輪子之自定義圓形圖片組件的實例代碼

一、背景

在采用Java配合xml佈局編寫鴻蒙app頁面的時候,發現sdk自帶的Image組件並不能將圖片設置成圓形,反復瞭翻閱瞭官方API手冊(主要查閱瞭Compont和Image相關的API),起初發現瞭一個setCornerRadius方法,於是想著將圖片寬度和高度設置為一樣,然後調用該方法將radios設置為寬度或者高度的一半,以為可以實現圓形圖片的效果,後來發現不行。於是乎想著能不能通過繼承原有的Image自己來動手重新自定義一個支持圓形的圖片組件。

二、思路:

1、對比之前自己在其他程序開發中自定義組件的思路,首先尋找父組件Image和Component相關的Api,看看是否具備OnDraw方法。

2、瞭解Canvas相關Api操作,特別是涉及到位圖的操作。

通過翻閱大量資料,發現瞭兩個關鍵的api,分別是Component的addDrawTask方法和其內部靜態接口DrawTask

三、自定義組件模塊

1、新建一個工程之後,創建一個獨立的Java FA模塊,然後刪除掉裡面所有佈局以及自動生成的java代碼,然後自己創建一個class繼承ImageView

2、寫一個類繼承ImageView,在其中暴露出public的設置圓形圖片的api方法以供後面調用;

3、在原有的Image組件獲取到位圖之後,利用該位圖數據利用addDrawTask方法配合Canvas進行位圖輸出形狀的重新繪制,這裡需要使用Canvas的一個

關鍵api方法drawPixelMapHolderRoundRectShape;

4、註意,為瞭讓Canvas最後輸出的圖片為圓形,需要將圖片在佈局中的寬度和高度設置成一樣,否則輸出的為圓角矩形或者橢圓形。

最後封裝後的詳細代碼如下:

package com.xdw.customview;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Image;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;

import java.io.InputStream;

/**
 * Created by 夏德旺 on 2021/1/1 11:00
 */
public class RoundImage extends Image {
 private static final HiLogLabel LABEL = new HiLogLabel(HiLog.DEBUG, 0, "RoundImage");
 private PixelMapHolder pixelMapHolder;//像素圖片持有者
 private RectFloat rectDst;//目標區域
 private RectFloat rectSrc;//源區域
 public RoundImage(Context context) {
 this(context,null);

 }

 public RoundImage(Context context, AttrSet attrSet) {
 this(context,attrSet,null);
 }

 /**
 * 加載包含該控件的xml佈局,會執行該構造函數
 * @param context
 * @param attrSet
 * @param styleName
 */
 public RoundImage(Context context, AttrSet attrSet, String styleName) {
 super(context, attrSet, styleName);
 HiLog.error(LABEL,"RoundImage");
 }

public void onRoundRectDraw(int radius){
 //添加繪制任務
 this.addDrawTask((view, canvas) -> {
  if (pixelMapHolder == null){
  return;
  }
  synchronized (pixelMapHolder) {
  //給目標區域賦值,寬度和高度取自xml配置文件中的屬性
  rectDst = new RectFloat(0,0,getWidth(),getHeight());
  //繪制圓角圖片
  canvas.drawPixelMapHolderRoundRectShape(pixelMapHolder, rectSrc, rectDst, radius, radius);
  pixelMapHolder = null;
  }
 });
 }

 //使用canvas繪制圓形
 private void onCircleDraw(){
 //添加繪制任務,自定義組件的核心api調用,該接口的參數為Component下的DrawTask接口
 this.addDrawTask((view, canvas) -> {
  if (pixelMapHolder == null){
  return;
  }
  synchronized (pixelMapHolder) {
  //給目標區域賦值,寬度和高度取自xml配置文件中的屬性
  rectDst = new RectFloat(0,0,getWidth(),getHeight());
  //使用canvas繪制輸出圓角矩形的位圖,該方法第4個參數和第5個參數為radios參數,
  // 繪制圖片,必須把圖片的寬度和高度先設置成一樣,然後把它們設置為圖片寬度或者高度一半時則繪制的為圓形
  canvas.drawPixelMapHolderRoundRectShape(pixelMapHolder, rectSrc, rectDst, getWidth()/2, getHeight()/2);
  pixelMapHolder = null;
  }
 });
 }

/**
 *獲取原有Image中的位圖資源後重新檢驗繪制該組件
 * @param pixelMap
 */
 private void putPixelMap(PixelMap pixelMap){
 if (pixelMap != null) {
  rectSrc = new RectFloat(0, 0, pixelMap.getImageInfo().size.width, pixelMap.getImageInfo().size.height);
  pixelMapHolder = new PixelMapHolder(pixelMap);
  invalidate();//重新檢驗該組件
 }else{
  pixelMapHolder = null;
  setPixelMap(null);
 }
 }

 /**
 * 通過資源ID獲取位圖對象
 **/
 private PixelMap getPixelMap(int resId) {
 InputStream drawableInputStream = null;
 try {
  drawableInputStream = getResourceManager().getResource(resId);
  ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
  sourceOptions.formatHint = "image/png";
  ImageSource imageSource = ImageSource.create(drawableInputStream, null);
  ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
  decodingOptions.desiredSize = new Size(0, 0);
  decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
  decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
  PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);
  return pixelMap;
 } catch (Exception e) {
  e.printStackTrace();
 } finally {
  try{
  if (drawableInputStream != null){
   drawableInputStream.close();
  }
  }catch (Exception e) {
  e.printStackTrace();
  }
 }
 return null;
 }

 /**
 * 對外調用的api,設置圓形圖片方法
 * @param resId
 */
 public void setPixelMapAndCircle(int resId){
 PixelMap pixelMap = getPixelMap(resId);
 putPixelMap(pixelMap);
 onCircleDraw();
 }

 /**
 * 對外調用的api,設置圓角圖片方法
 * @param resId
 * @param radius
 */
 public void setPixelMapAndRoundRect(int resId,int radius){
 PixelMap pixelMap = getPixelMap(resId);
 putPixelMap(pixelMap);
 onRoundRectDraw(radius);
 }
}

到此這篇關於鴻蒙HarmonyOS App開發造輪子之自定義圓形圖片組件的文章就介紹到這瞭,更多相關鴻蒙HarmonyOS自定義圓形圖片組件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: