自定义view学习笔记一:五角星绘制

本文记录了作者初次学习自定义Android View的过程,重点介绍了如何利用onMeasure(), onLayout(), onDraw()方法,特别是onDraw(),在Canvas上使用Paint绘制五角星。文章提到了确定五角星顶点坐标算法以及解决原点坐标位于左上角的问题,最后展示了绘制五角星的实现效果。" 129062274,16904120,MTK7621串口转换:业务到调试,"['运维', '串口通信', '硬件调试']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚开始学习自定义view,记录一下学习过程。
参考了网络上的一些博文,自定义view需要关注最多的就是3个方法:onMeasure(), onLayout(),onDraw(),而其中最关键的就是onDraw()方法了。而自定义view中我们需要做的就是在canvas上面通过paint来画出我们想要的图形,下面是画五角星的代码。

package com.leen.android.customviewtest;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import static java.lang.Math.PI;

public class AngleView extends View {
    private static String TAG = "AngleView";

    private int defaultWidth = 300;
    private int defaultHeight = 300;  //view的默认宽高
    private int mCenterX;
    private int mCenterY;  //view的中心点
    private int mBackgroudColor;
    private int mPaintColor;
    private int mRotation;  //五角星旋转角度

    private Paint mPaint;
    private Path mPath;

    public AngleView(Context context) {
        this(context, null);
    }

    public AngleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AngleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mBackgroudColor = Color.RED;
        mPaintColor = Color.YELLOW;
        mRotation = 0;

        if(mPaint == null)
            mPaint = new Paint();

        if(mPath == null)
            mPath = new Path();

        //setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        //mPaint.setAntiAlias(true);
    }

    private int getMySize(int measureSpec, int defaultSize) {
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);

        Log.d(TAG, "defaultSize=" + defaultSize + ", mode=" + mode + ", size=" + size);
        switch (mode) {
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                return defaultSize;
            case MeasureSpec.EXACTLY:
                return size;
            default:
                return defaultSize;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = getMySize(widthMeasureSpec, defaultWidth);
        int height = getMySize(heightMeasureSpec, defaultHeight);

        setMeasuredDimension(width, height);

        mCenterX = getMeasuredWidth() / 2;
        mCenterY = getMeasuredHeight() / 2;
        Log.d(TAG, "mCenterX=" + mCenterX + ", mCenterY=" + mCenterY);

        int r = getMeasuredWidth() / 3;  //五角星外接圆半径
        float angle = 72f;  //五个角对应的角度 360/5
        double rad = 2 * PI / 360;  //1度对应的弧度

        //五角星五个角顶点坐标算法:
        //x = r * cos(n * angle * rad)
        //y = r * sin(n * angle * rad)
        float a[] = {(float) (Math.cos(0 * angle * rad) * r), (float) (Math.sin(0 * angle * rad) * r)};
        float b[] = {(float) (Math.cos(1 * angle * rad) * r), (float) (-Math.sin(1 * angle * rad) * r)};
        float c[] = {(float) (Math.cos(2 * angle * rad) * r), (float) (-Math.sin(2 * angle * rad) * r)};
        float d[] = {(float) (Math.cos(3 * angle * rad) * r), (float) (-Math.sin(3 * angle * rad) * r)};
        float e[] = {(float) (Math.cos(4 * angle * rad) * r), (float) (-Math.sin(4 * angle * rad) * r)};

        mPath.moveTo(a[0], a[1]);
        mPath.lineTo(c[0], c[1]);
        mPath.lineTo(e[0], e[1]);
        mPath.lineTo(b[0], b[1]);
        mPath.lineTo(d[0], d[1]);
        mPath.close();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG, "onDraw()");

        mPaint.setColor(mPaintColor);
        canvas.translate(mCenterX, mCenterY);  //将画布原点移动到view中心
        canvas.drawColor(mBackgroudColor);
        canvas.rotate(mRotation);  //旋转画布,顺时针为正,逆时针为负
        canvas.drawPath(mPath, mPaint);
    }

    public void setColor(int backgroudColor, int paintColor) {
        mBackgroudColor = backgroudColor;
        mPaintColor = paintColor;
        invalidate();
    }

    public void setRotate(int rotate) {
        mRotation = rotate;
        invalidate();
    }
}

代码算比较简单了,我的做法是确定好五角星的五个顶点坐标,然后连成线,再填充。这个过程中也遇到了一些问题,比较关键的就是五个顶点坐标的算法,还有原点坐标默认是左上角,需要做个位移。
效果图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值