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

 更新时间:2021年01月05日 10:54:07   作者:HarmonyOS技术社区  
这篇文章主要介绍了鸿蒙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自定义圆形图片组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java数据结构基础:稀疏数组

    java数据结构基础:稀疏数组

    今天带大家了解一下Java稀疏数组的相关知识,文中有非常详细的介绍及代码示例,对正在学习java的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-08-08
  • Spring Security的过滤器链机制

    Spring Security的过滤器链机制

    过滤器作为 ​Spring Security​ 的重中之重,我们需要了解其中的机制,这样我们才能根据业务需求的变化进行定制,今天来探讨一下 ​Spring Security​ 中的过滤器链机制
    2022-08-08
  • SpringBoot内部外部配置文件加载顺序解析

    SpringBoot内部外部配置文件加载顺序解析

    这篇文章主要介绍了SpringBoot内部外部配置文件加载顺序解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Spring Boot中@value的常见用法及案例

    Spring Boot中@value的常见用法及案例

    @Value注解是Spring框架中强大且常用的注解之一,本文主要介绍了SpringBoot中@value的常见用法及案例,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • 详解使用Jenkins自动编译部署web应用

    详解使用Jenkins自动编译部署web应用

    本篇主要介绍基于Jenkins实现持续集成的方式,通过案例介绍线上自动编译及部署的配置过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • springmvc json类型转换错误解决方案

    springmvc json类型转换错误解决方案

    这篇文章主要介绍了springmvc json类型转换错误解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java中List分片方式详细解析

    Java中List分片方式详细解析

    这篇文章主要介绍了Java中List分片方式详细解析,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • 关于Integer.parseInt()方法的使用

    关于Integer.parseInt()方法的使用

    这篇文章主要介绍了关于Integer.parseInt()方法的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Spring使用@Autowired为抽象父类注入依赖代码实例

    Spring使用@Autowired为抽象父类注入依赖代码实例

    这篇文章主要介绍了Spring使用@Autowired为抽象父类注入依赖代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Java检测死锁案例

    Java检测死锁案例

    这篇文章主要介绍了Java检测死锁案例,本文列举了导致死锁的程序,通过使用jconsole工具进行检测等,讲述了避免死锁的方法,需要的朋友可以参考下
    2021-07-07

最新评论