canvas教程

自定义控件之绘图篇:Canvas与图层(一)

字号+ 作者:H5之家 来源:H5之家 2017-08-27 18:01 我要评论( )

自定义控件之绘图篇:Canvas与图层(一),一、如何获得一个Canvas对象 方法一:自定义view时, 重写onDraw、dispatchDraw方法 (1)、定义 我们先来看一下onDraw

一、如何获得一个Canvas对象 方法一:自定义view时, 重写onDraw、dispatchDraw方法 (1)、定义 我们先来看一下onDraw、dispatchDraw方法的定义

(Canvas canvas) {
(Canvas canvas) {
super.dispatchDraw(canvas);
}

可以看到onDraw、dispatchDraw在传入的参数中都有一个canvas对象。这个canvas对象是View中的Canvas对象,利用这个canvas对象绘图,效果会直接反应在View中;
(2)、onDraw、dispatchDraw区别

  • onDraw()的意思是绘制视图自身
  • dispatchDraw()是绘制子视图
  • 无论是View还是ViewGroup对它们俩的调用顺序都是onDraw()->dispatchDraw()
    但在ViewGroup中,当它有背景的时候就会调用onDraw()方法,否则就会跳过onDraw()直接调用dispatchDraw();所以如果要在ViewGroup中绘图时,往往是重写dispatchDraw()方法
    在View中,onDraw()和dispatchDraw()都会被调用的,所以我们无论把绘图代码放在onDraw()或者dispatchDraw()中都是可以得到效果的,但是由于dispatchDraw()的含义是绘制子控件,所以原则来上讲,在绘制View控件时,我们是重新onDraw()函数
    所以结论来了:
    在绘制View控件时,需要重写onDraw()函数,在绘制ViewGroup时,需要重写dispatchDraw()函数。
    方法二:使用Bitmap创建 1、构建方法 使用:

    Canvas canvas = new Canvas(bitmap);

    Canvas canvas = new Canvas();
    canvas.setBitmap(bitmap);

    其中bitmap可以从图片加载,也可以创建,有下面几种方法

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.wave_bg,null);

    这两个方法是最常用的,除了这两个方法以外,还有其它几个方法(比如构造一个具有matrix的图像副本——前面示例中的倒影图像),这里就不再涉及了,大家可以去查看Bitmap的构造函数。
    2、在OnDraw()中使用 我们一定要注意的是,如果我们用bitmap构造了一个canvas,那这个canvas上绘制的图像也都会保存在这个bitmap上,而不是画在View上,如果想画在View上就必须使用OnDraw(Canvas canvas)函数中传进来的canvas画一遍bitmap才能画到view上。
    下面举个例子:

    Paint Canvas BitmapCanvasView(Context context= .setColor(Color.= Bitmap.Bitmap.Config.= (Canvas canvas) {
    .setTextSize(.drawText();
    }
    }

    我们先看一下运行结果:


    可以看到,毛线也没有,这是为什么呢?
    我们仔细来看一下onDraw函数:

    (Canvas canvas) {
    .setTextSize(.drawText();
    } 在onDraw函数中,我们只是将文字画在了mBmpCanvas上,也就是我们新建mBmp图片上!这个图片跟我们view没有任何关系好吧,我们需要把mBmp图片画到view上才行,所以我们在onDraw中需要加下面这句,将mBmp画到view上

    canvas.drawBitmap();

    所以改造后的代码为:

    RectFboundsleftrightsaveFlags)

  • RectF bounds:要保存的区域的矩形。
  • int saveFlags:取值有:ALL_SAVE_FLAG、MATRIX_SAVE_FLAG、CLIP_SAVE_FLAG、HAS_ALPHA_LAYER_SAVE_FLAG、FULL_COLOR_LAYER_SAVE_FLAG、CLIP_TO_LAYER_SAVE_FLAG总共有这六个,其中ALL_SAVE_FLAG表示保存全部内容,这些标识的具体意义我们后面会具体讲;
  • 第二个构造函数实际与第一个是一样的,只不过是根据四个点来构造一个矩形。
    下面我们来看一下例子,拿xfermode来做下试验,来看看saveLayer都干了什么:


    这段代码大家应该很熟悉,这是我们在讲解setXfermode()时的示例代码,但在saveLayer前把整个屏幕画成了绿色,效果图如下:


    那么问题来了,如果我们把saveLayer给去掉,看看会怎样:

    Canvascanvascanvas); canvasColorcanvasdstBmpmPaint); mPaintPorterDuffXfermodecanvassrcBmpheightmPaint); mPaint

    效果图就变这样了:


    我擦类……去掉saveLayer()居然效果都不一样了……
    我们先回顾下Mode.SRC_IN的效果:在处理源图像时,以显示源图像为主,在相交时利用目标图像的透明度来改变源图像的透明度和饱和度。当目标图像透明度为0时,源图像就完全不显示。
    再回过来看结果,第一个结果是对的,因为不与圆相交以外的区域透明度都是0,而第二个图像怎么就变成了这屌样,源图像全部都显示出来了。

    (1)、saveLayer的绘图流程 这是因为在调用saveLayer时,会生成了一个全新的bitmap,这个bitmap的大小就是我们指定的保存区域的大小,新生成的bitmap是全透明的,在调用saveLayer后所有的绘图操作都是在这个bitmap上进行的。
    所以:

    widthheightmPaintcanvasdstBmpmPaint); mPaintPorterDuffXfermodecanvassrcBmpheightmPaint);

    ,而在saveLayer新生成的bitmap上,只有dstBmp对应的圆形,所以除了与圆形相交之外的位置都是空像素。
    在画图完成之后,会把saveLayer所生成的bitmap盖在原来的canvas上面。
    所以此时的xfermode的合成过程如下图所示:


     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • HTML5 Canvas实现圆形并显示百分比的进度条实例详解

      HTML5 Canvas实现圆形并显示百分比的进度条实例详解

      2017-08-28 08:00

    • canvas一周一练 canvas基础学习

      canvas一周一练 canvas基础学习

      2017-08-27 16:00

    • UGUI初学习Canvas

      UGUI初学习Canvas

      2017-08-27 15:01

    • Canvas从入门到放弃(三)

      Canvas从入门到放弃(三)

      2017-08-27 12:01

    网友点评