一、背景
在采用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自定义圆形图片组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!