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

概述

在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);
    }

运行结果是这样的

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

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

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

1.画布的裁剪

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

setLayerType(LAYER_TYPE_SOFTWARE,null);

  • clipOutRect()系列的函数,主要用来裁剪出一个矩形之外的部分
  • clipRect()系列的函数,主要用来裁剪出一个矩形
  • clipOutPath()系列的函数,主要用来裁剪出一个路径外的部分,一般是封闭的图形
  • clipPath()系列的函数,主要用来裁剪出一个路径内的部分,一般为封闭图形

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

  • 保存
    int save()
  • 恢复
    void restore()
  • 恢复到指定状态
    void restoreToCount(int saveCount)
    这里我们结合一个具体的例子来进行说明,例子的绘制步骤是这样的
  • 1.给Canvas一个绿色背景
  • 2.保存Canvas状态
  • 3.在中心裁剪出一个矩形
  • 4.在裁剪后的Canvas中加入灰色背景色
  • 5.恢复画布状态
  • 6.在恢复后的Canvas上画一个裁剪范围之外的蓝色的矩形框
    好了我们开始写代码,代码也很简单

@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);
    }

运行结果如下

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

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

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

运行后变成了这样

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

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

总结

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

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...