zoukankan      html  css  js  c++  java
  • 鸿蒙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

    鸿蒙HarmonyOS App开发造轮子之--自定义圆形图片组件

    鸿蒙HarmonyOS App开发造轮子之--自定义圆形图片组件

    三、自定义组件模块

    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);
        }
    }

    查看更多章节>>> 

    作者:软通夏德旺

    想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com/

  • 相关阅读:
    Hbase学习记录(2)| Shell操作
    Hbase学习记录(1)|伪分布式安装
    Zookeeper集群安装详解
    防范xss的正确姿势
    怎么样通过编写Python小程序来统计测试脚本的关键字
    XSS报警机制(前端防火墙:第二篇)
    XSS姿势——文件上传XSS
    MySQL防范SQL注入风险
    SQL注入—我是如何一步步攻破一家互联网公司的
    通过BurpSuite和sqlmap配合对dvwa进行sql注入测试和用户名密码暴力破解
  • 原文地址:https://www.cnblogs.com/HarmonyOS/p/14234447.html
Copyright © 2011-2022 走看看