一、如何获得一个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区别
但在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 = BitmapFactory.decodeResource(getResources(),R.drawable.wave_bg,null);
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函数:
.setTextSize(.drawText();
} 在onDraw函数中,我们只是将文字画在了mBmpCanvas上,也就是我们新建mBmp图片上!这个图片跟我们view没有任何关系好吧,我们需要把mBmp图片画到view上才行,所以我们在onDraw中需要加下面这句,将mBmp画到view上
canvas.drawBitmap();
所以改造后的代码为:
RectFboundsleftrightsaveFlags)
下面我们来看一下例子,拿xfermode来做下试验,来看看saveLayer都干了什么:
那么问题来了,如果我们把saveLayer给去掉,看看会怎样:
Canvascanvascanvas); canvasColorcanvasdstBmpmPaint); mPaintPorterDuffXfermodecanvassrcBmpheightmPaint); mPaint
效果图就变这样了:
我擦类……去掉saveLayer()居然效果都不一样了……
我们先回顾下Mode.SRC_IN的效果:在处理源图像时,以显示源图像为主,在相交时利用目标图像的透明度来改变源图像的透明度和饱和度。当目标图像透明度为0时,源图像就完全不显示。
再回过来看结果,第一个结果是对的,因为不与圆相交以外的区域透明度都是0,而第二个图像怎么就变成了这屌样,源图像全部都显示出来了。
所以:
widthheightmPaintcanvasdstBmpmPaint); mPaintPorterDuffXfermodecanvassrcBmpheightmPaint);
,而在saveLayer新生成的bitmap上,只有dstBmp对应的圆形,所以除了与圆形相交之外的位置都是空像素。在画图完成之后,会把saveLayer所生成的bitmap盖在原来的canvas上面。
所以此时的xfermode的合成过程如下图所示: