自定义View(四):onDraw()绘图详解

1、onDraw()方法的作用

在自定义View中,onDraw()过程是最后一步也是最难掌握的一步,因为其涉及方法之多和写法之灵活实在令人难以捉摸,他的主要作用是“画图”,现在我们来以一个简单的例子示范一下View是如何绘图的。

2、重写onDraw()方法

新建一个MyView类继承View并实现其四个构造方法,我们先看看onDraw()方法

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
}

可以看到onDraw()方法中有一个参数canvas,这个canvas就是画板,自定义View就是在画板上作画,关于Canvas类的众多画图方法请看官方文档 Canvas Api,这里我们只讲几个简单的例子。
首先我们尝试在canvas上面画一个矩形canvas.drawRect()
drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
很显然前面四个参数分别代表矩形的左、上、右、下坐标,而最后一个参数Paint则为“画笔”的意思,关于Paint的更多方法请查阅官方文档Paint Api,所以我们要先定义一个画笔。
Paint paint_g=new Paint();
paint_g.setARGB(50,0,0xff,0);

先看看setARGB()方法


setARGB(int a, int r, int g, int b)

从字面意思我们可以 这四个参数分别是:透明度、红色、绿色、蓝色,这次我们设置的是一个透明度为50%的绿色画笔。贴上onDraw()的完整代码


@Override
protected void onDraw(Canvas canvas) {
    Paint paint_g=new Paint();
    //透明度为50的绿色画笔
    paint_g.setARGB(50,0,0xff,0);

    //在画板上画一个铺满整个View的绿色矩形
    canvas.drawRect(0,0,getWidth(),getHeight(),paint_g);
}


运行结果如下:
自定义View(四):onDraw()绘图详解


好的,我们再在这个矩形上面画一个圆试试看

@Override
protected void onDraw(Canvas canvas) {
    Paint paint_g=new Paint();
    //透明度为50的绿色画笔
    paint_g.setARGB(50,0,0xff,0);

    //在画板上画一个铺满整个View的绿色矩形
    canvas.drawRect(0,0,getWidth(),getHeight(),paint_g);

    Paint paint_r=new Paint();
    //透明度为50的红色画笔
    paint_r.setARGB(50,0xff,0,0);

    //在画板上画一个圆心在View中间,半径为View宽度四分之一的红色圆
    //第一个参数是圆心的x坐标,第二个参数是圆心的y坐标,第三个参数是半径,第四个参数是画笔
    canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/4,paint_r);
}

运行结果如下

自定义View(四):onDraw()绘图详解

自定义View就是这样一个一个图形画上去最终达到自己想要的效果。

3、尝试动态画图

我们再重写onTouchEvent方法,如下


@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            touch_x=event.getX();
            touch_y=event.getY();
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_x=event.getX();
            touch_y=event.getY();
            invalidate();//重绘视图 
            break;
        case MotionEvent.ACTION_UP:
            touch_x=0;
            touch_y=0;
            invalidate();//重绘视图
            break;
    }
    return true;
}

@Override
protected void onDraw(Canvas canvas) {
    Paint paint_g=new Paint();
    //透明度为50的绿色画笔
    paint_g.setARGB(50,0,0xff,0);

    //在画板上画一个铺满整个View的绿色矩形
    canvas.drawRect(0,0,getWidth(),getHeight(),paint_g);


    if (touch_x!=0&touch_y!=0){
        Paint paint_r=new Paint();
        paint_r.setARGB(50,0xff,0,0);
        canvas.drawCircle(touch_x,touch_y,getWidth()/4,paint_r);
    }
}


touch_x和touch_y是MyView的两个成员变量,用来记录触摸的点,在onDraw方法中,以触摸点为圆心绘圆,当两点都为0的时候则不绘圆形。
运行效果:

自定义View(四):onDraw()绘图详解


从效果图中可以看到当触摸时就会显示圆,并会跟着触摸点移动。上完整代码:

public class MyView extends View {
    private float touch_x=0,touch_y=0;
    private Canvas canvas;


    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                touch_x=event.getX();
                touch_y=event.getY();
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_x=event.getX();
                touch_y=event.getY();
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_x=0;
                touch_y=0;
                postInvalidate();
                break;
        }
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint_g=new Paint();
        //透明度为50的绿色画笔
        paint_g.setARGB(50,0,0xff,0);

        //在画板上画一个铺满整个View的绿色矩形
        canvas.drawRect(0,0,getWidth(),getHeight(),paint_g);


        if (touch_x!=0&touch_y!=0){
            Paint paint_r=new Paint();
            paint_r.setARGB(50,0xff,0,0);
            canvas.drawCircle(touch_x,touch_y,getWidth()/4,paint_r);
        }
    }
}


4、源码链接


https://github.com/Hasagit/DrawDemo.git