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

相关文章

  • spring AOP自定义注解方式实现日志管理的实例讲解

    spring AOP自定义注解方式实现日志管理的实例讲解

    下面小编就为大家分享一篇spring AOP自定义注解方式实现日志管理的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • java自带排序使用

    java自带排序使用

    这篇文章主要给大家分享了java自带排序使用,该方法是升序排序,方法的内部采用了快排实现,但该方法是 稳定的。下面一起来看看文章的详细介绍吧
    2021-12-12
  • 使用Java8实现观察者模式的方法(上)

    使用Java8实现观察者模式的方法(上)

    本文给大家介绍使用java8实现观察者模式的方法,涉及到java8观察者模式相关知识,对此感兴趣的朋友一起学习吧
    2016-02-02
  • 用Java实现小球碰壁反弹的简单实例(算法十分简单)

    用Java实现小球碰壁反弹的简单实例(算法十分简单)

    下面小编就为大家带来一篇用Java实现小球碰壁反弹的简单实例(算法十分简单)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • java 如何给对象中的包装类设置默认值

    java 如何给对象中的包装类设置默认值

    这篇文章主要介绍了java 如何给对象中的包装类设置默认值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • JDBC编程实现文件、图片的存储方法

    JDBC编程实现文件、图片的存储方法

    这篇文章主要介绍了JDBC编程实现文件、图片的存储方法,以实例形式分析了Java基于JDBC操作数据库的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • 关于JWT之token令牌认证登录

    关于JWT之token令牌认证登录

    这篇文章主要介绍了关于JWT之token令牌认证登录,使用JWT能够保证Token的安全性,且能够进行Token时效性的检验,使用JWT时,登录成功后将用户信息生成一串令牌字符串,需要的朋友可以参考下
    2023-05-05
  • Java拦截器、过滤器和监听器的区别与作用详解

    Java拦截器、过滤器和监听器的区别与作用详解

    Java 拦截器、过滤器和监听器是在 Java Web 开发中常用的组件,它们各有特点和用途,下面将分别介绍它们的区别和作用,并提供具体的代码示例,需要的朋友可以参考下
    2025-06-06
  • JavaScript实现贪吃蛇游戏

    JavaScript实现贪吃蛇游戏

    这篇文章主要为大家详细介绍了JavaScript实现贪吃蛇游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • spring强行注入和引用实例解析

    spring强行注入和引用实例解析

    这篇文章主要介绍了spring强行注入和引用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09

最新评论