HarmonyOS技术社区 · 2020年09月29日

鸿蒙开发实战系列之一:圆角

前言

看过鸿蒙2.0系统的发布会,大家是不是蠢蠢欲动,想要开发第一个鸿蒙的程序呢,网上有很多文章介绍鸿蒙系统、跟Android的区别以及怎么写HelloWorld的文章,这边就不复制粘贴了。

今天换个花样,来看下如何实现Android里面一些常见功能与效果,因为鸿蒙刚出来不久,一切都还不是很成熟(没有前辈的神器),只能靠自己手x代码,废话不多说,来看下鸿蒙系统里如何实现基本的图片圆角功能吧。

如今大部分美术在设计样式的时候,都会给图片带上圆角,在鸿蒙开发过程中,一定会遇到要对图片进行二次处理,添加上圆角、或者圆形图像。

Android产品:这个图加下圆角吧,应该花不了你3分钟吧? 
开发小蒙:喵的,这是鸿蒙,没有glide,怎么玩,给我3天先 。
Android产品:gun,忽悠老子呢,你以为我第一天当产品么?圆角这么简单的事,还需要3天,你是不是花2天半打酱油去了么。
开发小蒙:卒。。。。。。 

小蒙好歹也是多年Android开发的老手,怎么会轻易认输,经过一番翻箱倒柜,查找鸿蒙api文档,终于实现了如下效果:
图片.png

界面背景为灰色,图片布局背景为红色,图片布局中放了一张正方形的图片,被裁减成了圆角矩形,那么这个效果是怎么实现的呢?

我们以往在Android的开发过程中,要做到这个效果,常规的解决方案有以下三种

1、使用Glide

2、自定义ImageView

3、直接操作图片绘制

在鸿蒙系统中,暂时没有Glide(可能很久之后才会有),直接操作图片的Api相对也还不够完善,所以我们选择的是自定义组件,具体做法如下:

首先你要能够跟据官方的文档,完整运行出Hello World程序(废话),不行的请自行解决

1、新建一个布局文件main_abilityslice_layout.xml,一个真实布局居中嵌套一个方向布局

<?xml version="1.0" encoding="utf-8"?>
<DependentLayout xmlns:ohos="http://schemas.huawei.com/res/harmonyos"
                   ohos:width="match_parent"
                   ohos:height="match_parent"
                   ohos:background_element="#ffffff"
                   ohos:gravity="center">
    <DirectionalLayout
            ohos:id="$+id:image_directional_layout"
            ohos:width="100dp"
            ohos:height="100dp"
            ohos:background_element="#ff0000"
            ohos:orientation="vertical"
    />
</DependentLayout>

2、新建一个自定义组件RoundRectView继承自Image组件

public class RoundRectView extends Image {
    private static final int radius = 20;//圆角半径,如果设置成图片的宽度的一半,则会图片变成圆形
    private PixelMapHolder pixelMapHolder;//像素图片持有者
    private RectFloat rectDst;//目标区域
    private RectFloat rectSrc;//源区域
    
    public RoundRectView(Context context, Size viewSize) {//Size是该视图显示区域的大小
         super(context);
         onDraw();
        rectDst = new RectFloat(0,0,viewSize.width,viewSize.height);
    }

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

    private void onDraw(){
        //添加绘制任务
        this.addDrawTask((view, canvas) -> {
            if (pixelMapHolder == null){
                return;
            }
            synchronized (pixelMapHolder) {
                //绘制圆角矩形图片
                canvas.drawPixelMapHolderRoundRectShape(pixelMapHolder, rectSrc, rectDst, radius, radius);
                pixelMapHolder = null;
            }
        });
    }
}

3、将图片、组件与视图进行绑定

public class MainAbilitySlice extends AbilitySlice {
    DirectionalLayout imageDirectionalLayout;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        initView();
    }

    private void initView(){
        setUIContent(ResourceTable.Layout_main_abilityslice_layout);
        imageDirectionalLayout = (DirectionalLayout)findComponentById(ResourceTable.Id_image_directional_layout);
        RoundRectView rectView = new RoundRectView(this,new Size(SizeUtils.dp2px(100),SizeUtils.dp2px(100)));
        rectView.putPixelMap(getPixelMap(ResourceTable.Media_test));//设置图片,ID需要先编译后才能识别到,当前图片资源放置在resources/base/media/test.png
        DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(DirectionalLayout.LayoutConfig.MATCH_PARENT,DirectionalLayout.LayoutConfig.MATCH_PARENT);
        imageDirectionalLayout.addComponent(rectView,layoutConfig);
    }
    
    /**
    * 通过资源ID获取位图对象
    **/
    private PixelMap getPixelMap(int drawableId) {
        InputStream drawableInputStream = null;
        try {
            drawableInputStream = BaseApplication.getInstance().getResourceManager().getResource(drawableId);
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = "image/png";
            ImageSource imageSource = ImageSource.create(drawableInputStream, sourceOptions);
            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;
    }
} 

经过以上几步操作之后,就可以做出一个鸿蒙版的圆角图片了,hiahiahia,终于可以站起身跟产品回复了:给我3分钟,哥给你lu出来。

以上情节,纯属yy与改编,如有雷同,请对号入座。

总结

鸿蒙是一款“面向未来”的操作系统,一款基于微内核的面向全场景的分布式操作系统,现已适配智慧屏,未来它将适配手机、平板、电脑、智能汽车、可穿戴设备等多终端设备。

鸿蒙系统做了很多封装和扩展屏蔽掉底层的工作,在多智能设备、万物互联的5G时代具有很大的优势,并且经过几天的玩耍,感觉鸿蒙的开发跟Android开发还是有很多相似之处,对于Android开发人员来说”极其友好“,极其容易上手。 所以让我们拥抱未来,学习鸿蒙吧。


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

推荐阅读
关注数
3010
内容数
446
华为鸿蒙相关技术,活动及资讯,欢迎关注及加入创作
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息