鸿蒙HarMonyOS的自定义组件之五星红旗

Posted 笔触狂放

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鸿蒙HarMonyOS的自定义组件之五星红旗相关的知识,希望对你有一定的参考价值。

使用Java语言开发鸿蒙系统应用的自定义组件五角星,并绘制红旗。

如果对自定义组件并不了解的同学请先看【鸿蒙】HarMonyOS的自定义组件一

我们知道所有的组件都是继承至Component类,我们绘制五角星也不例外,我们先定义一个类继承至Component类,并实现几个构造方法

public class StarsChinaComponentextends Component{
 
     public StarsChinaComponent(Context context) {
        super(context);
        
    }
 
     public StarsChinaComponent(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }
}

 接下来设置自定义组件的宽度和高度,这个设置需要实现Component.EstimateSizeListener接口,并在构造方法中添加宽高改变事件,同时重写onEstimateSize方法

public class StarsChinaComponent extends Component implements
        Component.EstimateSizeListener{
 
     public StarsChinaComponent(Context context) {
        super(context);
        //添加组件大小监听器
        setEstimateSizeListener(this);
        
    }
 
     public StarsChinaComponent(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }
 
     @Override
    public boolean onEstimateSize(int i, int i1) {
        /*i = (int) (radius * Math.cos(degree2Radian(DEGREE) / 2) * 2);
        i1 = (int) (radius + radius
                * Math.cos(degree2Radian(DEGREE)));*/
        int w = Component.EstimateSpec.getSize(i);
        int h = Component.EstimateSpec.getSize(i1);
        setEstimatedSize(
                //NOT_EXCEED 已为子组件确定了最大大小,子组件不能超过指定大小。
                //PRECISE 父组件已确定子组件的大小。
                //UNCONSTRAINT 父组件对子组件没有约束,表示子组件可以任意大小。
                Component.EstimateSpec.getChildSizeWithMode(w, w, EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(h, h, EstimateSpec.NOT_EXCEED)
        );
        return true;
    }
}

接下来初始化画笔参数,设置绘制图形的时候所需要的颜色,线条的宽度,是否需要填充图形等等

public class StarsChinaComponent extends Component implements
        Component.EstimateSizeListener{
    // 画笔
    private Paint paint;
     public StarsChinaComponent(Context context) {
        super(context);
        //添加组件大小监听器
        setEstimateSizeListener(this);
         //初始化画笔
        initPaint();
        
    }
 
     public void initPaint() {
        //创建画笔
        paint = new Paint();
        //设置画笔颜色
        paint.setColor(Color.YELLOW);
        //设置线条宽度
        paint.setStrokeWidth(20);
        //设置线条样式
        //STROKE_STYLE 空心线条
        //FILL_STYLE 实心
        //FILLANDSTROKE_STYLE实心和边框线条
        paint.setStyle(Paint.Style.FILL_STYLE);
    }
 
     public StarsChinaComponent(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }
 
     @Override
    public boolean onEstimateSize(int i, int i1) {
        /*i = (int) (radius * Math.cos(degree2Radian(DEGREE) / 2) * 2);
        i1 = (int) (radius + radius
                * Math.cos(degree2Radian(DEGREE)));*/
        int w = Component.EstimateSpec.getSize(i);
        int h = Component.EstimateSpec.getSize(i1);
        setEstimatedSize(
                //NOT_EXCEED 已为子组件确定了最大大小,子组件不能超过指定大小。
                //PRECISE 父组件已确定子组件的大小。
                //UNCONSTRAINT 父组件对子组件没有约束,表示子组件可以任意大小。
                Component.EstimateSpec.getChildSizeWithMode(w, w, EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(h, h, EstimateSpec.NOT_EXCEED)
        );
        return true;
    }
}

那么接下来开始绘制五角星,绘制五角星需要分析五角星的绘制过程,我们通过数学的几何图形这么课程可以知道,绘制五角星需要将一个圆平均切为10个圆弧作为五角星的十个连接点,所有我们需要设置圆的半径,圆弧的角度为36°

public class StarsChinaComponent extends Component implements
        Component.EstimateSizeListener{
    private float radius = 20;//绘制五角星的圆形半径
    private int color = 0xFF0000;//默认的颜色
    private final static float DEGREE = 36; // 五角星角度
    // 画笔
    private Paint paint;
    
     public StarsChinaComponent(Context context) {
        super(context);
        //添加组件大小监听器
        setEstimateSizeListener(this);
         //初始化画笔
        initPaint();
        
    }
 
    public float getRadius() {
        return radius;
    }
 
    public void setRadius(float radius) {
        this.radius = radius;
    }
 
    public int getColor() {
        return color;
    }
 
    public void setColor(int color) {
        this.color = color;
    }
 
     public void initPaint() {
        //创建画笔
        paint = new Paint();
        //设置画笔颜色
        paint.setColor(Color.GRAY);
        //设置线条宽度
        paint.setStrokeWidth(20);
        //设置线条样式
        //STROKE_STYLE 空心线条
        //FILL_STYLE 实心
        //FILLANDSTROKE_STYLE实心和边框线条
        paint.setStyle(Paint.Style.FILL_STYLE);
    }
 
     public StarsChinaComponent(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }
 
     @Override
    public boolean onEstimateSize(int i, int i1) {
        /*i = (int) (radius * Math.cos(degree2Radian(DEGREE) / 2) * 2);
        i1 = (int) (radius + radius
                * Math.cos(degree2Radian(DEGREE)));*/
        int w = Component.EstimateSpec.getSize(i);
        int h = Component.EstimateSpec.getSize(i1);
        setEstimatedSize(
                //NOT_EXCEED 已为子组件确定了最大大小,子组件不能超过指定大小。
                //PRECISE 父组件已确定子组件的大小。
                //UNCONSTRAINT 父组件对子组件没有约束,表示子组件可以任意大小。
                Component.EstimateSpec.getChildSizeWithMode(w, w, EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(h, h, EstimateSpec.NOT_EXCEED)
        );
        return true;
    }
}

接下来需要实现Component.DrawTask接口,并重写onDraw方法,通过Canvas绘制图层和图形

public class StarsChinaComponent extends Component implements
        Component.EstimateSizeListener, Component.DrawTask,{
    private float radius = 20;//绘制五角星的圆形半径
    private int color = 0xFF0000;//默认的颜色
    private final static float DEGREE = 36; // 五角星角度
    // 画笔
    private Paint paint;
    
     public StarsChinaComponent(Context context) {
        super(context);
        //添加组件大小监听器
        setEstimateSizeListener(this);
         //初始化画笔
        initPaint();
        // 添加绘制任务
        addDrawTask(this);
    }
 
    public float getRadius() {
        return radius;
    }
 
    public void setRadius(float radius) {
        this.radius = radius;
    }
 
    public int getColor() {
        return color;
    }
 
    public void setColor(int color) {
        this.color = color;
    }
 
     public void initPaint() {
        //创建画笔
        paint = new Paint();
        //设置画笔颜色
        paint.setColor(Color.GRAY);
        //设置线条宽度
        paint.setStrokeWidth(20);
        //设置线条样式
        //STROKE_STYLE 空心线条
        //FILL_STYLE 实心
        //FILLANDSTROKE_STYLE实心和边框线条
        paint.setStyle(Paint.Style.FILL_STYLE);
    }
 
     public StarsChinaComponent(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }
 
     @Override
    public boolean onEstimateSize(int i, int i1) {
        /*i = (int) (radius * Math.cos(degree2Radian(DEGREE) / 2) * 2);
        i1 = (int) (radius + radius
                * Math.cos(degree2Radian(DEGREE)));*/
        int w = Component.EstimateSpec.getSize(i);
        int h = Component.EstimateSpec.getSize(i1);
        setEstimatedSize(
                //NOT_EXCEED 已为子组件确定了最大大小,子组件不能超过指定大小。
                //PRECISE 父组件已确定子组件的大小。
                //UNCONSTRAINT 父组件对子组件没有约束,表示子组件可以任意大小。
                Component.EstimateSpec.getChildSizeWithMode(w, w, EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(h, h, EstimateSpec.NOT_EXCEED)
        );
        return true;
    }
 
    @Override
    public void onDraw(Component component, Canvas canvas) {
        Path path = new Path();
        float radian = degree2Radian(DEGREE);
        float radius_in = (float) (radius * Math.sin(radian / 2) / Math
                .cos(radian)); // 中间五边形的半径
 
        path.moveTo((float) (radius * Math.cos(radian / 2)), 0);
        path.lineTo(
                (float) (radius * Math.cos(radian / 2) + radius_in
                        * Math.sin(radian)),
                (float) (radius - radius * Math.sin(radian / 2)));
        path.lineTo((float) (radius * Math.cos(radian / 2) * 2),
                (float) (radius - radius * Math.sin(radian / 2)));
        path.lineTo(
                (float) (radius * Math.cos(radian / 2) + radius_in
                        * Math.cos(radian / 2)), (float) (radius + radius_in
                        * Math.sin(radian / 2)));
        path.lineTo(
                (float) (radius * Math.cos(radian / 2) + radius
                        * Math.sin(radian)),
                (float) (radius + radius * Math.cos(radian)));
        path.lineTo((float) (radius * Math.cos(radian / 2)),
                (float) (radius + radius_in));
        path.lineTo(
                (float) (radius * Math.cos(radian / 2) - radius
                        * Math.sin(radian)),
                (float) (radius + radius * Math.cos(radian)));
        path.lineTo(
                (float) (radius * Math.cos(radian / 2) - radius_in
                        * Math.cos(radian / 2)), (float) (radius + radius_in
                        * Math.sin(radian / 2)));
        path.lineTo(0, (float) (radius - radius * Math.sin(radian / 2)));
        path.lineTo(
                (float) (radius * Math.cos(radian / 2) - radius_in
                        * Math.sin(radian)),
                (float) (radius - radius * Math.sin(radian / 2)));
 
        path.close();
        canvas.drawPath(path, paint);
    }
 
    /**
     * 角度转弧度
     *
     * @param degree
     * @return
     */
    private float degree2Radian(float degree) {
        //把一个圆分成五份
        return (float) (Math.PI * degree / 180);
    }
}

这时候一个五角星就绘制完成了。那么接下来我们需要AbilitySlice类展示组件,然后动态创建一个绝对布局,并设置宽度为填充整个手机屏幕高宽,高度为600,创建五个五角星组件对象,更改五角星的半径来调整五角星的大小,一个大五角星,四个小吴江行,设置其五角星的高宽和绘制半径,以及五角星的大小,并将绘制的五角星添加至现形布局,最后将布局加载至界面进行渲染即可。

package com.example.hm_phone_java.slice;

import com.example.hm_phone_java.views.StarsChinaComponent;
import com.example.hm_phone_java.views.StarsComponent;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.PositionLayout;
import ohos.agp.components.element.ShapeElement;

public class ChinaAbilitySlice extends AbilitySlice {

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        //创建绝对布局
        PositionLayout pl=new PositionLayout(this);
        //设置绝对布局的宽度填充整个屏幕,高度为600
        ComponentContainer.LayoutConfig config=
                new ComponentContainer.LayoutConfig(
                        ComponentContainer.LayoutConfig.MATCH_PARENT,
                        600);
        //将宽高信息设置给绝对布局
        pl.setLayoutConfig(config);
        //设置背景颜色为红色
        ShapeElement element=new ShapeElement();
        element.setRgbColor(new RgbColor(255,0,0));
        pl.setBackground(element);

        //创建大五角星组件对象
        StarsChinaComponent component = new StarsChinaComponent(this);
        //设置五角星显示在绝对布局的哪个位置
        component.setPosition(vp2px(20),vp2px(35));
        //设置五角星的绘制半径
        component.setRadius(100);
        //设置五角星的高宽
        DirectionalLayout.LayoutConfig lc=new DirectionalLayout.LayoutConfig(200,200);
        lc.setMargins(10,10,10,10);
        //将参数添加至五角星组件对象
        component.setLayoutConfig(lc);
        //将五角星添加至线性布局
        pl.addComponent(component);

        //创建小五角星组件对象
        StarsChinaComponent component1 = new StarsChinaComponent(this);
        //设置五角星显示在绝对布局的哪个位置
        component1.setPosition(vp2px(95),vp2px(10));
        //设置五角星的绘制半径
        component1.setRadius(40);
        //将参数添加至五角星组件对象
        component1.setLayoutConfig(lc);
        //将五角星添加至线性布局
        pl.addComponent(component1);

        //创建小五角星组件对象
        StarsChinaComponent component2 = new StarsChinaComponent(this);
        //设置五角星显示在绝对布局的哪个位置
        component2.setPosition(vp2px(120),vp2px(35));
        //设置五角星的绘制半径
        component2.setRadius(40);
        //将参数添加至五角星组件对象
        component2.setLayoutConfig(lc);
        //将五角星添加至线性布局
        pl.addComponent(component2);


        //创建小五角星组件对象
        StarsChinaComponent component3 = new StarsChinaComponent(this);
        //设置五角星显示在绝对布局的哪个位置
        component3.setPosition(vp2px(120),vp2px(75));
        //设置五角星的绘制半径
        component3.setRadius(40);
        //将参数添加至五角星组件对象
        component3.setLayoutConfig(lc);
        //将五角星添加至线性布局
        pl.addComponent(component3);

        //创建小五角星组件对象
        StarsChinaComponent component4 = new StarsChinaComponent(this);
        //设置五角星显示在绝对布局的哪个位置
        component4.setPosition(vp2px(95),vp2px(100));
        //设置五角星的绘制半径
        component4.setRadius(40);
        //将参数添加至五角星组件对象
        component4.setLayoutConfig(lc);
        //将五角星添加至线性布局
        pl.addComponent(component4);


        //将线性布局加载至界面显示
        super.setUIContent(pl);

    }

    /**
     * 单位转换的方法
     * @param vp
     * @return
     */
    private int vp2px(float vp){
        return AttrHelper.vp2px(vp,this);
    }
}

将该ChinaAbilitySlice添加至主界面中

package com.example.hm_phone_java;
 
import com.example.hm_phone_java.slice.*;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
 
public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        //设置启动页
        super.setMainRoute(ChinaAbilitySlice.class.getName());
    }
}

最后启动华为模拟器,即可看到效果。

以上是关于鸿蒙HarMonyOS的自定义组件之五星红旗的主要内容,如果未能解决你的问题,请参考以下文章

鸿蒙HarMonyOS的自定义组件之抽奖大转盘

鸿蒙HarMonyOS的自定义组件一

鸿蒙HarMonyOS的UI组件学习八之网站引入

鸿蒙HarMonyOS的UI组件学习七之图片轮播

HarmonyOS鸿蒙学习笔记@Component注解自定义组件简单说明

HarmonyOS鸿蒙学习笔记@Component注解自定义组件简单说明