自定义view绘图篇--Paint与Canvas

通过自定义view基础我们对自定义view也有所了解啦。然而我们在安卓开发中或许会见过这样的特效:手机管家的清理垃圾、安卓的饼状图、手机直播界面的泡泡上浮(使用到了贝塞尔曲线)。其实这些特效都是自定义view的实现,确切的说是 动画+自定义绘图。这里我们就分章节慢慢深入,总结下这些知识点。

绘图篇系列

1、自定义view绘图篇–Paint与Canvas

2、自定义view绘图篇–Canvas的变换

3、自定义view绘图篇–Path

4、自定义view绘图篇–图片和文字的绘制

5、自定义view绘图篇–贝塞尔曲线

本篇知识点

自定义view绘图篇--Paint与Canvas_第1张图片

一、了解Paint 和Canvas

1、paint:英文原意为“涂料”的意思,安卓里面理解为画笔。
2、Canvas:英文原意为“帆布”的意思,安卓里面理解为画布。
所以我们只需要使用画笔在画布上画图案即可。

二、常用方法

我们或许都知道现实中作画的一些东西吧:比如不同颜色的画笔、画出不同粗细线条的画笔、不同背景色的画布、等等。其实安卓中对画笔画笔进行了封装。
1、Paint:这个类代表画笔,凡是跟画的东西设置相关的都是画笔的功能比如:

画笔颜色、线条大小、填充样式、抗锯齿、阴影等等、、、

2、Canvas:这个类代表画布,凡是跟画出的形状、不同的样品相关都是由这个类控制比如:

画圆、画椭圆、画线、等等、、、
ps:在重写view的onDraw方法时有个形参就是Canvas对象,我们可以直接使用

1、Paint常用的方法

(1)构造方法

// 无参数的调用有参数的
 public Paint() {
        this(0);//无参数的默认使用了默认值为0的flag
    }
 
  /**
     * Create a new paint with the specified flags. Use setFlags() to change
     * these after the paint is created.
     *
     * @param flags initial flag bits, as if they were passed via setFlags().
     */  
     // 根据确切的flags创建一个画笔,可以使用setFlags方法去改变flag在画笔对象创建后。
 public Paint(int flags) {
  ···
 }

常见Paint类中flag 常量:

  • ANTI_ALIAS_FLAG
    开启抗锯齿功能和paint.setAntiAlias(true)功能一致,一般我们在创建对象时传递这个参数。
  • DITHER_FLAG
    在绘制时启用抖动
  • 等等、、、
    参看Paint类源码内的常量或者查看google api 文档
    ps:antialias ['æntɪ’eɪlɪəs] 抗锯齿、平滑

(2)普通方法

1、 public void setColor(int color) 设置画笔颜色
2、public void setAntiAlias(boolean aa) 是否开启抗锯齿
3、public void setStrokeWidth(float width)设置画笔描边宽度 (有默认值大约1dp)
4、public void setStyle(Style style) 设置画笔的风格有三种枚举值 (不设置时默认填充)

  • Paint.Style.STROKE 只描边
  • Paint.Style.FILL 填充
  • Paint.Style.FILL_AND_STROKE 填充并且描边
    ps:参考下图理解

5、public void setShadowLayer(float radius, float dx, float dy, int shadowColor) 设置阴影,参数为阴影半径、水平竖直的移动距离、阴影颜色。

(3)setStyle的枚举值效果(以画圆为例子)

填充效果: paint.setStyle(Paint.Style.FILL)// 或者不设置,系统会默认填充。
自定义view绘图篇--Paint与Canvas_第2张图片

只描边不填充效果: paint.setStyle(Paint.Style.STROKE);
自定义view绘图篇--Paint与Canvas_第3张图片

注意:
1、这里设置了描边宽度为30,其实你把描边宽度设置为0他也默认为1dp左右。
2、我们把描边宽度设置较大时,圆就变成圆环啦!!!
3、Paint.Style.FILL_AND_STROKE的效果和Paint.Style.FILL看着几乎一样

2、Canvas常用方法

画布的相关api较多这里我们就以详细的栗子介绍下常用的方法

(1)在作图之前我们首先要初始化一下我们的画笔:

/**
 * Created by sunnyDay on 2019/7/25 10:34
 * 画笔和画布的基本操作
 */
public class BasicView extends View {

    private Paint paint;

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

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

    public BasicView(Context context,  AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 1、初始化画笔
        paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setFlags(Paint.ANTI_ALIAS_FLAG);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(5);
        paint.setStyle(Paint.Style.FILL);
    }

    /**
     * 这里了进行绘图相关的操作
     * */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);// 画布默认背景
        
        // 2、开始作图
       
    }
}

(2)画布背景

canvas.drawColor(Color.WHITE);// 画布默认背景

(3)画点

点动成线,线动成面。可见点就是最基础的图案,所以我们也从最基础的点开始。

常用方法:


//参数:x点坐标,y点坐标,画笔对象。
public void drawPoint(float x, float y, @NonNull Paint paint)//画一个点: 
//参数:点数组,画笔对象
public void drawPoints(float[] pts, @NonNull Paint paint)// 画多个点

简单实践:

// 点数组
  private float[]points = new float[]{
            300,200,
            300,300,
            300,400
    };
    ···
        // 2、开始作图
        canvas.drawPoint(100,100,paint); // 单个点
        canvas.drawPoints(points,paint);//多个点

效果:
自定义view绘图篇--Paint与Canvas_第4张图片

ps:画多个点时如果你少一个点坐标的Y值这点就不会画出,点从你数组里面声明的顺序两两一对。

(2)画线

数学里面常说“两点一线”所以我们画线同样需要两点即可。

常用方法:

// 参数:线的起点和终点坐标、画笔
public void drawLine(float startX, float startY, float stopX, float stopY,Paint paint) // 画一条线

// 线的集合、画笔
public void drawLines(float[] pts,  Paint paint) //画多条线

简单实践:

  private float[] points = new float[]{
            300, 200,
            300, 300,
            300, 400,
            300, 500
    };
···

  // 2、开始作图
        canvas.drawLine(100, 100,  200, 200, paint);


        canvas.drawLines(points, paint);


效果:
自定义view绘图篇--Paint与Canvas_第5张图片
收获:
和点的使用类似

ps:画多条线时如果你少一个终点坐标的Y值这条线就不会画出,线从你数组里面声明的顺序两两一对。

(3)画矩形

规则:绘制矩形需要矩形一条对角线上的两个顶点即可(任意一条对角线都行)

方法:
在这里插入图片描述

1、首先看参数多的第三个方法:左上,右下这不正是矩形的对角线的两个顶点吗?我们传入参数再传入画笔对象即可。
2、再看前两个方法:参数Rect、RectF其实就是对矩形的封装,一个是int数值,一个是Float类型数值

简单实践:

  // 2、开始作图
        canvas.drawRect(50,50,200,200,paint);

        Rect rect = new Rect(250,50,400,200); //建议 new 操作不要放在 onDraw方法中
        paint.setColor(Color.RED);
        canvas.drawRect(rect,paint);

效果:
自定义view绘图篇--Paint与Canvas_第6张图片

(4)绘制椭圆

了解椭圆:

自定义view绘图篇--Paint与Canvas_第7张图片

其实椭圆是有两个半径的rx、ry。当rx=ry是我们看到的就是圆形

方法:
在这里插入图片描述

观察api我们发现这参数和矩形一样,就是方法名不一样,小样换个马甲我就不认识你了?

实践:

  RectF rect = new RectF(50, 50, 500, 300);  //建议 new 操作不要放在 onDraw方法中

        paint.setColor(Color.YELLOW);
        canvas.drawRect(rect, paint);//画矩形

        // 2、开始作图
        paint.setColor(Color.RED);
        canvas.drawOval(rect, paint); // 画椭圆

效果图:
自定义view绘图篇--Paint与Canvas_第8张图片

1、参考下效果图我们也可看出其实我们画的椭圆就是矩形的内切椭圆
2、当矩形变为正方形时,椭圆也就变成了圆

(5)画圆角矩形
在这里插入图片描述

看看方法我们会发现圆角矩形和矩形差不多,无非是多了一个参数,其实这个rx,ry就是圆角的半径。
注意:
1、当rx=ry我们画的矩形的四个圆角是规则的
2、当rx!=ry时我们就可能画成椭圆

栗子:

 RectF rect = new RectF(50, 50, 400, 400);  //建议 new 操作不要放在 onDraw方法中

        paint.setColor(Color.RED);
        canvas.drawRoundRect(rect,50,50, paint);//画圆角矩形(rx=ry时)

        paint.setColor(Color.RED);
        canvas.drawRoundRect(50,500,400,600,100,300, paint);//画圆角矩形(rx!=ry时)

效果:
自定义view绘图篇--Paint与Canvas_第9张图片

一般我们画的圆角都是规则的 让 rx=ry即可(画椭圆有专门的api)

(6)画圆
在这里插入图片描述

圆形就简单啦,圆心坐标+半径确定一个圆

  canvas.drawCircle(200,200,100,paint);

效果:
自定义view绘图篇--Paint与Canvas_第10张图片

(7)画圆弧

圆弧就有意思啦,当我们绘制圆弧时选择画笔填充(FILL)+useCenter 就可以画出圆的某一部分,继而画出饼状图。

api:

 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)

public void drawArc(float left, float top, float right, float bottom, float startAngle,
            float sweepAngle, boolean useCenter,  Paint paint)

两个方法,和前面的椭圆类似,我们看第一个方法即可。
1、RectF oval 和椭圆的参数一样
2、startAngle 开始角度
3、sweepAngle 圆弧扫描过得角度
4、useCenter 是否使用中心(椭圆或者圆的圆心位置)
理解:其实就是在矩形内画圆弧

简单实践:

7.1 Paint.Style.STROKE+useCenter (true)

  RectF rectF = new RectF(100, 100, 300, 300);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(rectF,paint); // 画矩形

        paint.setStyle(Paint.Style.STROKE); 
        paint.setColor(Color.RED);
        canvas.drawArc(rectF, 0, 90, true, paint); // 画圆弧

自定义view绘图篇--Paint与Canvas_第11张图片
7.2 Paint.Style.FILL+useCenter (true)

 RectF rectF = new RectF(100, 100, 300, 300);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(rectF,paint); // 画矩形

        paint.setStyle(Paint.Style.FILL); 
        paint.setColor(Color.RED);
        canvas.drawArc(rectF, 0, 90, true, paint); // 画圆弧

自定义view绘图篇--Paint与Canvas_第12张图片

7.3 Paint.Style.STROKE+useCenter (false)

    RectF rectF = new RectF(100, 100, 300, 300);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(rectF,paint); // 画矩形

        paint.setStyle(Paint.Style.STROKE); //Paint.Style.STROKE
        paint.setColor(Color.RED);
        canvas.drawArc(rectF, 0, 90, false, paint); // 画圆弧 

自定义view绘图篇--Paint与Canvas_第13张图片

7.4 扫描角度
自定义view绘图篇--Paint与Canvas_第14张图片

注意:
1、注意开始角度和扫描角度
2、扫描角度不要理解为结束角度
3、当你的矩阵为正方形时画的就是圆弧,当矩阵为长方形时画的就是椭圆的弧

四、圆弧实战-简单饼状图

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);// 画布默认背景

        RectF rectF = new RectF(300, 300, 600, 600);

        paint.setColor(Color.RED);
        canvas.drawArc(rectF, 0, 45, true, paint); // 画圆弧 红

        paint.setColor(Color.GRAY);
        canvas.drawArc(rectF, 45, 45, true, paint); // 画圆弧  灰

        paint.setColor(Color.BLUE);
        canvas.drawArc(rectF, 90, 30, true, paint); // 画圆弧  蓝

        paint.setColor(Color.GREEN);
        canvas.drawArc(rectF, 120, 80, true, paint); // 画圆弧  绿

        paint.setColor(Color.BLACK);
        canvas.drawArc(rectF, 200, 160, true, paint); // 画圆弧  黑
        
    }

效果:
自定义view绘图篇--Paint与Canvas_第15张图片

虽然没有百分比、每一部分的名字,但是基本的饼状图已经出来啦,快乐啦马飞飞。。。。在接下来学习中我们再完善。

五、小结

画笔没啥操作,画布的操作多啦,我们这几就是简单的画几何形状,其实画布还有很多功能,如下部分功能:
更多功能参考:Android Developer — Canvas

自定义view绘图篇--Paint与Canvas_第16张图片

上面常见的方法也不少,按照学习顺序其实可以归纳几类的(个人理解):
1、画笔和基本图形(对应上表的绘制基本形状)
2、画布变化操作(对应上表快照、画布变化)
3、绘制Path
4、绘制文字
5、Path-----贝塞尔
5、其他的方法平时遇见时总结下

下一篇:自定义view绘图篇–Canvas的变换
参考文章:
Canvas之绘制基本形状

自定义控件之绘图篇(一):概述及基本几何图形绘制

安卓自定义View进阶-画笔基础(Paint)

你可能感兴趣的:(android)