Android自定义View(4) 《Canvas基本使用》

2021-08-29  本文已影响0人  非典型程序猿

概述

在Android中,我们经常会需要去绘制一些自己需要的控件,所以继承自View的自定义View就产生了。这篇文章主要介绍在View中的重要类,Canvas类的一些基本使用。

Canvas绘制背景

Canvas绘制背景主要有几个方法

    /**
     * 使用srcover-porterduff模式,用指定的颜色填充整个画布的位图(限于当前剪辑)
     *
     * @param color the color to draw onto the canvas
     */
    public void drawColor(@ColorInt int color) {
        super.drawColor(color);
    }
   /**
     * 使用srcover-porterduff模式,用指定的颜色填充整个画布的位图(限于当前剪辑)
     *
     * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color}
     *              class for details about {@code ColorLong}s.
     * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong}
     *                                  is invalid or unknown.
     */
    public void drawColor(@ColorLong long color){
        super.drawColor(color, BlendMode.SRC_OVER);
    }
   /**
     * 使用指定的颜色和porter duff xfermode填充整个画布的位图(仅限于当前剪辑)。
     *
     * @param color the color to draw onto the canvas
     * @param mode the porter-duff mode to apply to the color
     */
    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
        super.drawColor(color, mode);
    }
   /**
     * 使用指定的颜色和blendmode填充整个画布的位图(仅限于当前剪辑)。
     *
     * @param color the color to draw onto the canvas
     * @param mode the blendmode to apply to the color
     */
    public void drawColor(@ColorInt int color, @NonNull BlendMode mode) {
        super.drawColor(color, mode);
    }
  /**
     * 使用指定的颜色和blendmode填充整个画布的位图(仅限于当前剪辑)。
     *
     * @param color the {@code ColorLong} to draw onto the canvas. See the {@link Color}
     *              class for details about {@code ColorLong}s.
     * @param mode the blendmode to apply to the color
     * @throws IllegalArgumentException if the color space encoded in the {@code ColorLong}
     *                                  is invalid or unknown.
     */
    public void drawColor(@ColorLong long color, @NonNull BlendMode mode) {
        super.drawColor(color, mode);
    }

画布的平移

一般采用下面的方法进行canvas的平移

   /**
     * Preconcat the current matrix with the specified translation
     *
     * @param dx The distance to translate in X
     * @param dy The distance to translate in Y
    */
    public void translate(float dx, float dy) {
        if (dx == 0.0f && dy == 0.0f) return;
        nTranslate(mNativeCanvasWrapper, dx, dy);
    }

这个方法可以将canvas的参考坐标平移,并不是平移之前已经绘制的内容,看下面一个例子大家就明白了,代码步骤是这样

@Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        Log.d(TAG,"onDraw");
        // 设置画笔的宽度
        paint.setStrokeWidth(5f);
        // 设置画笔的颜色
        paint.setColor(Color.RED);
        // 设置画笔的Style
        paint.setStyle(Paint.Style.STROKE);
        // 绘制一个矩形
        canvas.drawRect(rectF,paint);
        // 平移画布
        canvas.translate(100,100);
        // 绘制矩形
        rectF = new RectF(width/2-300,height/2-150,width/2+300,height/2+150);
        canvas.drawRect(rectF,paint);
    }

运行结果是这样的


device-2021-08-29-185700.png

明白了吧,canvas只是你绘制时的一个图层而已,当你平移之后,并不影响之前已经绘制过的内容,所以在使用平移画布时请记得这点。

Canvas的裁剪,状态的保存和恢复

1.画布的裁剪

在学习裁剪之前,需要先搞清楚一个概念,这里画布的裁剪的意义与我们所理解的裁剪纸张的意义是不一样的,这里的裁剪好比你原本可以在一张完整的纸上进行绘制,裁剪后,就好像你的纸张被一张透明的玻璃盖住,中间你裁剪的部分就是空心的,可以往下面的纸张上继续画东西,其余部分则无法绘制,你只能看到之前绘制的内容,你如果裁剪出是一个圆形,那么你就是在这个圆中绘制你的内容,但是这并不影响显示你之前已经在纸上绘制出来的内容.
非常重要的点
裁剪是不可逆的 ! ! !
裁剪是不可逆的 ! ! !
裁剪是不可逆的 ! ! !
所以我们在使用裁剪时如果需要恢复,是必须要结合画布的保存和恢复一起使用的.裁剪使用的方法主要有以下几种
还要注意一点 使用裁剪时需要关闭硬件加速

setLayerType(LAYER_TYPE_SOFTWARE,null);

2.画布的状态保存与恢复

@Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        Log.d(TAG,"onDraw");
        // 设置画笔的宽度
        paint.setStrokeWidth(10f);
        // 设置画笔的颜色
        paint.setColor(Color.BLUE);
        // 设置画笔的Style
        paint.setStyle(Paint.Style.STROKE);

        // 绘制背景色绿色
        canvas.drawColor(Color.GREEN);
        // 保存此时画布状态
        int saveCount = canvas.save();
        // 在画布中间裁剪出一个矩形
        RectF rectF = new RectF(width/2-300,height/2-150,width/2+300,height/2+150);
        canvas.clipRect(rectF);
        // 绘制灰色背景方便观察
        canvas.drawColor(Color.GRAY);
        // 恢复画布状态,即裁剪之前
        canvas.restoreToCount(saveCount);
        // canvas.restore(); 恢复至上一个保存状态,这里和canvas.restoreToCount(saveCount)效果是一致的,择一调用即可。
        // 恢复后绘制一个矩形
        RectF rectB = new RectF(20,20,width-20,height-20);
        canvas.drawRect(rectB,paint);
    }

运行结果如下


device-2021-08-29-200319.png

为了验证我们的Canvas恢复是有效的,我们把恢复的代码注释掉,像这样

        // 恢复画布状态,即裁剪之前
        // canvas.restoreToCount(saveCount);

运行后变成了这样


device-2021-08-29-200553.png

我们最后绘制的蓝色矩形框没了,所以裁剪后在裁剪范围外绘制的内容是无效的,但是裁剪前绘制的内容是不影响显示的,所以这样可以理解裁剪时类似透明玻璃层的概念了吧

总结

Canvas的背景绘制,平移,状态保存和恢复就整理到这里了,下篇总结一下视图动画~

上一篇下一篇

猜你喜欢

热点阅读