一、背景

在采用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);

}

}

5、修改config.json文件,代码如下{

"app": {

"bundleName": "com.xdw.customview",

"vendor": "xdw",

"version": {

"code": 1,

"name": "1.0"

},

"apiVersion": {

"compatible": 4,

"target": 4,

"releaseType": "Beta1"

}

},

"deviceConfig": {},

"module": {

"package": "com.xdw.customview",

"deviceType": [

"phone",

"tv",

"tablet",

"car",

"wearable"

],

"reqPermissions": [

{

"name": "ohos.permission.INTERNET"

}

],

"distro": {

"deliveryWithInstall": true,

"moduleName": "roundimage",

"moduleType": "har"

}

}

}

这样该模块就可以导出后续给其他所有工程引用了,后面还可以编译之后发布到gradle上直接通过添加依赖来进行使用(这个是后话),下面我们先通过本地依赖导入的方式来调用这个自定义组件模块吧。

四、其他工程调用该自定义组件并测试效果

1、再来新建一个工程,然后将之前的模块导入到新建的工程中(DevEco暂时不支持自动导入外部模块的操作,需要手动导入操作,请关注我的另外一篇博客)

2、在gradle中引用导入的模块的组件,代码如下:

文章后续内容和相关附件可以点击下面的原文链接前往学习

HarmonyOS图片,HarmonyOS App开发造轮子--自定义圆形图片组件相关推荐

  1. 鸿蒙os事例代码,鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码

    一.背景 在采用Java配合xml布局编写鸿蒙app页面的时候,发现sdk自带的Image组件并不能将图片设置成圆形,反复了翻阅了官方API手册(主要查阅了Compont和Image相关的API),起 ...

  2. Android 自定义圆形图片 CircleImageView

    1.效果预览 1.1.布局中写自定义圆形图片的路径即可 1.2.然后看一看图片效果 1.3.原图是这样的 @mipmap/ic_launcher 2.使用过程 2.1.CircleImageView源 ...

  3. Android 自定义圆形图片

    代码注释很多,简单说下思路,然后直接贴代码 1.截取选定图片中间区域(宽等于高的正方形) 2.按照控件大小进行缩放 3.画圆,设置paint.setXfermode(new PorterDuffXfe ...

  4. Kotlin实战练习——自定义圆形图片三种实现方式

    Kotlin实战练习--自定义圆形图片三种实现方式 前言 如今Kotlin越来越重要,本人也开始了Kotlin的学习.为了检测学习效果,加深学习印象,同时回顾一下以前的一些知识点,决定从写一个自定义圆 ...

  5. Unity 自定义圆形图片

    使用Mask组件的缺点 我们知道项目中可以这样展示圆形图片,一般是Image组件,下面再加上一个圆形Mask.但是这样做有几个缺点: 使用Mask会额外消耗多一个Drawcall来创建Mask,做像素 ...

  6. vue图片img加载失败显示自定义默认图片(缺省图)

    vue图片img加载失败显示自定义默认图片(缺省图) 1.图片加载示例  2.加载失败显示默认图片  3.加载失败默认图片代码处理 <div class="book-img" ...

  7. Android图片缓存框架 - Fresco实现圆角或圆形图片 (四)

    目录 1.Fresco 简介 2. Fresco 文档 3. Fresco开发步骤 4. Fresco加载图片6种方式 5. Drawees xm属性设置 6 Fresco实现圆角或圆形图片 6.1 ...

  8. Delphi D10.X安卓APP开发让原生Toast显示图片

    上次完成了<Delphi D10.X安卓APP开发中简单使用原生Toast>,可以快速方便的使用Toast,并且可以自定义显示位置.在此基础上,今天我们来实现在Toast中显示图片的方式. ...

  9. QML | 自定义圆形图片按钮

    在一个项目中需要做一个圆形图片按钮的列表,就自己实现了下. 此按钮有两个自定义属性,分别表示按钮按下时和未按下时候显示的图片,还有一个rbClicked信号为按钮点击的响应信号. //RoundBut ...

最新文章

  1. win7关闭系统索引服务器,win7系统关闭磁盘索引功能的操作方法
  2. 恭喜《软件随想录》得到了大家的一致认可!
  3. oracle 管道化表函数(Pipelined Table) [转]
  4. redis数据结构之一:链表
  5. MySQL组内排序取最大值
  6. hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数
  7. bootstrap中点击左边展开
  8. 实战篇 | 基于freeRTOS的多任务事件传输demo(附代码)
  9. 天胶指数发布 对话国际农民丰收节贸易会海垦集团走出去
  10. PrimeFaces:在动态生成的对话框中打开外部页面
  11. pta输出三角形字符阵列c语言,C语言l|博客园作业11
  12. android+内存清理+代码,最新版本:Android一键式清理,内存清理功能的实现
  13. Kubernetes事件离线工具kube-eventer正式开源
  14. openstack 重启mysql_openstack 重启服务命令
  15. windows镜像_什么是windows镜像?什么是Ghost?它们有什么优缺点?
  16. R7-2 谁是赢家 (10 分)
  17. Spring Security:基于内存的角色授权
  18. rtems源码树结构
  19. gurobi和java,在Java中使用Gurobi与在Ampl中使用Gurobi
  20. 人工智能AI系列 - 问答系统

热门文章

  1. 那些被疯狂追求的女孩,后来怎么样了?
  2. 苹果iOS版手机云便签无法同意用户协议正常使用怎么解决?
  3. Python毕业设计 机器学习股票数据量化分析与预测系统 - python 大数据
  4. u盘装linux 5.8,用U盘安装centos5.8网络版
  5. OpenStack OVS GRE/VXLAN
  6. 什么是网络爬虫,网络爬虫的职能是什么
  7. 广东迅视看社保迎来5个变化!
  8. 风控中产品设计与贷前/中/后的四大模块都有哪些内容
  9. Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
  10. MYSQL的启动图标不见了,怎么办?很简单,一步到位!!