★60.自定义控件 ★04.Canvas之绘制图形

Canvas介绍

Canvas 我们可以称之为画布,能够在上面绘制各种东西,是安卓平台2D图形绘制的底层,非常强大。

绘制颜色

绘制颜色是填充整个画布,常用于绘制底色。

canvas.drawColor(Color.BLUE); //绘制蓝色
★60.自定义控件 ★04.Canvas之绘制图形_第1张图片

画笔(Paint)

创建

要想绘制内容,首先需要先创建一个画笔,如下:

// 创建一个画笔
Paint Paint = new Paint();
Paint.setColor(Color.BLACK);       //设置画笔颜色
Paint.setStyle(Paint.Style.FILL);  //设置画笔模式为填充
Paint.setStrokeWidth(10f);         //设置画笔宽度为10px

模式介绍

画笔模式 描述
STROKE 描边
FILL 填充
FILL_AND_STROKE 描边加填充

示例

Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(40);     //为了实验效果明显,特地设置描边宽度非常大

// 描边
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(200,200,100,paint);

// 填充
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(200,500,100,paint);

// 描边加填充
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(200, 800, 100, paint);
★60.自定义控件 ★04.Canvas之绘制图形_第2张图片

绘制点

可以绘制一个点,也可以绘制一组点,如下:

canvas.drawPoint(200, 200, mPaint);     //在坐标(200,200)位置绘制一个点
canvas.drawPoints(new float[]{          //绘制一组点,坐标位置由float数组指定
      500,500,
      500,600,
      500,700
},mPaint);
★60.自定义控件 ★04.Canvas之绘制图形_第3张图片

绘制直线

绘制直线需要两个点,初始点和结束点,同样绘制直线也可以绘制一条或者绘制一组:

canvas.drawLine(300,300,500,600,mPaint);    // 在坐标(300,300)(500,600)之间绘制一条直线
canvas.drawLines(new float[]{               // 绘制一组线 每四数字(两个点的坐标)确定一条线
    100,200,200,200,
    100,300,200,300
},mPaint);
★60.自定义控件 ★04.Canvas之绘制图形_第4张图片

绘制矩形

确定一个矩形最少需要四个数据,就是对角线的两个点的坐标值,这里一般采用左上角和右下角的两个点的坐标。

// 第一种
canvas.drawRect(100,100,800,400,mPaint);

// 第二种
Rect rect = new Rect(100,100,800,400);
canvas.drawRect(rect,mPaint);

// 第三种
RectF rectF = new RectF(100,100,800,400);
canvas.drawRect(rectF,mPaint);
★60.自定义控件 ★04.Canvas之绘制图形_第5张图片

绘制圆角矩形

// 第一种
RectF rectF = new RectF(100,100,800,400);
canvas.drawRoundRect(rectF,30,30,mPaint);

// 第二种:API 21
canvas.drawRoundRect(100,100,800,400,30,30,mPaint);

示例图:


★60.自定义控件 ★04.Canvas之绘制图形_第6张图片

红线标注的 rx 与 ry 就是两个半径,也就是相比绘制矩形多出来的那两个参数。


★60.自定义控件 ★04.Canvas之绘制图形_第7张图片

当你让rx大于宽度的一半,ry大于高度的一半时,你会发现圆角矩形变成了一个椭圆,他们画出来是这样的。


★60.自定义控件 ★04.Canvas之绘制图形_第8张图片

绘制椭圆

// 第一种
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);

// 第二种
canvas.drawOval(100,100,800,400,mPaint);
★60.自定义控件 ★04.Canvas之绘制图形_第9张图片

绘制圆

canvas.drawCircle(500,500,400,mPaint);  // 绘制一个圆心坐标在(500,500),半径为400 的圆。

绘制圆弧

// startAngle  开始角度
// sweepAngle  扫过角度
// useCenter   是否使用中心

// 第一种
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}

// 第二种
public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) {}

以下示例图是0-90度,但是否画出中心分别是false和true的结果。


★60.自定义控件 ★04.Canvas之绘制图形_第10张图片

饼状图示例

数据

public class PieData {
    // 用户关心数据
    private String name;        // 名字
    private float value;        // 数值
    private float percentage;   // 百分比

    // 非用户关心数据
    private int color = 0;      // 颜色
    private float angle = 0;    // 角度

    public PieData(@NonNull String name, @NonNull float value) {
        this.name = name;
        this.value = value;
    }
}

绘制

public class PieView extends View {
    // 颜色表 (注意: 此处定义颜色使用的是ARGB,带Alpha通道的)
    private int[] mColors = {0xFFCCFF00, 0xFF6495ED, 0xFFE32636, 0xFF800000, 0xFF808000, 0xFFFF8C69, 0xFF808080,
            0xFFE6B800, 0xFF7CFC00};
    // 饼状图初始绘制角度
    private float mStartAngle = 0;
    // 数据
    private ArrayList mData;
    // 宽高
    private int mWidth, mHeight;
    // 画笔
    private Paint mPaint = new Paint();

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

    public PieView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
    }

    // 重点部分
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (null == mData)
            return;
        float currentStartAngle = mStartAngle;                    // 当前起始角度
        canvas.translate(mWidth / 2, mHeight / 2);                // 将画布坐标原点移动到中心位置
        float r = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);  // 饼状图半径
        RectF rect = new RectF(-r, -r, r, r);                     // 饼状图绘制区域

        for (int i = 0; i < mData.size(); i++) {
            PieData pie = mData.get(i);
            mPaint.setColor(pie.getColor());
            canvas.drawArc(rect, currentStartAngle, pie.getAngle(), true, mPaint);
            currentStartAngle += pie.getAngle();
        }

    }

    // 设置起始角度
    public void setStartAngle(int mStartAngle) {
        this.mStartAngle = mStartAngle;
        invalidate();   // 刷新
    }

    // 设置数据
    public void setData(ArrayList mData) {
        this.mData = mData;
        initData(mData);
        invalidate();   // 刷新
    }

    // 初始化数据
    private void initData(ArrayList mData) {
        if (null == mData || mData.size() == 0)   // 数据有问题 直接返回
            return;

        float sumValue = 0;
        for (int i = 0; i < mData.size(); i++) {
            PieData pie = mData.get(i);

            sumValue += pie.getValue();       //计算数值和

            int j = i % mColors.length;       //设置颜色
            pie.setColor(mColors[j]);
        }

        float sumAngle = 0;
        for (int i = 0; i < mData.size(); i++) {
            PieData pie = mData.get(i);

            float percentage = pie.getValue() / sumValue;   // 百分比
            float angle = percentage * 360;                 // 对应的角度

            pie.setPercentage(percentage);                  // 记录百分比
            pie.setAngle(angle);                            // 记录角度大小
            sumAngle += angle;

            Log.i("angle", "" + pie.getAngle());
        }
    }
}

效果图

★60.自定义控件 ★04.Canvas之绘制图形_第11张图片

你可能感兴趣的:(★60.自定义控件 ★04.Canvas之绘制图形)