在前面的章节中,我们已经介绍了Canvas的一些基本操作,今天我们继续讲解,Canvas类的用法,可见这个类在自定义View中是多么的重要。今天我们来着重介绍一下如何绘制图片和文字。在这一章节学习之后我们基本上对于一些简单的自定义View就可以搞定了。但是这仅仅是刚刚开始,我还会继续带领大家深入的学习下去,做出更多更炫酷的自定义控件出来。
第一、drawPicture绘制图片
上面是官网中提供的此类的方法,beginRecording()意思为开始录制,什么意思呢。看一段官网的解释再说:To record a picture, call beginRecording() and then draw into the Canvas that is returned. Nothing we appear on screen, but all of the draw commands (e.g.drawRect(Rect, Paint)
) will be recorded. To stop recording, call endRecording(). After endRecording() the Canvas that was returned must no longer be used, and nothing should be drawn into it.意思是此方法开始记录一幅画,就是canvas的操作。直到endRecording()方法的调用,结束录制。注意:endRecording()调用之后此画布必须保证不再使用。什么意思呢,我们可以通俗的理解为,此方法的操作是可以记录一个画布,然后重复的使用,每次使用都是和上一次一样的。是不是这样可以大大减少我们的内存开支,只要首次加载的时候绘制一遍,之后每次都使用记录的内容就可以。后面是getHeight和getWidth两个方法,获取宽和高很简单就不说了。最后一个输出流,可以看到在API18之后已经废弃了,就先不考虑了。
第二、Picture的使用步骤
1、初始化对象
//第一步创建Pictureprivate Picture mPicture = new Picture();
2、录制画布的操作
//开始录制绘制的内容private void recording(){//开始录制图片,返回一个canvas,此canvas的所有操作都将会被录制。 Canvas canvas = mPicture.beginRecording(500,500); //创建一个画笔 Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); //位移画布中心点坐标一段距离 canvas.translate(500,500); //绘制一个圆 canvas.drawCircle(0,0,300,paint); //录制结束 mPicture.endRecording();}
3、调用
public CustomPictureText(Context context, AttributeSet attrs) {super(context, attrs); // 调用录制 recording();}
4、开始绘制
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas); mPicture.draw(canvas);}
5、结果如图
7、绘制的方法有很多,以上的方法在低版本中可能会影响Canvas的状态。下面我们来介绍Canvas为我们提供的绘制方法。来比较一下有什么差别
public void drawPicture (Picture picture)public void drawPicture (Picture picture, Rect dst)public void drawPicture (Picture picture, RectF dst)
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawPicture(mPicture,new RectF(0,0,mPicture.getWidth(),200));}
效果如图:
如图所示我们的圆变成了椭圆,是什么造成的呢,这里我们的绘制的时候传入了一个矩形,这个矩形就是用来压缩我们的begin开始录制的时候返回的画布的,当时我们设置为500,500.可以看到我们这里的方法是宽保持不变,高度变为原来的二分之一一,就把原来的圆压缩为现在的椭圆了。
8.将Picture包装成为PictureDrawable,使用PictureDrawable的draw方法绘制。
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//包装成drawablePictureDrawable drawable = new PictureDrawable(mPicture);//设置绘制的区域drawable.setBounds(0,0,500,mPicture.getHeight());drawable.draw(canvas);}
注意这里的setBounds方法,来设置的是绘制区域,设置的是现在onDraw方法里边的画布,而不是我们picture的画布。设置的区域为左边左上角0,0.到500,图片高度。这里将会展示出来一个四分之一的圆。
第三、drawBitmap绘制图片
一提到Bitmap可能大多数的小伙伴都会有一种莫名其妙的不知所措,什么内存溢出了,内存泄漏了,好像很多都是和Bitmap有关的,但是今天我们不会深入的去研究这里边的原理,今天我们先介绍一下,使用drawBitmap来绘制我们的图片资源。既然是绘制Bitmap那么我们肯定需要先获取到Bitmap才对。获取Bitmap我们使用BitmapFactory来获取,他可以获取,手机存储卡,资源文件,网络图片转换为我们使用的Bitmap。其实还有其他的两种方法,但是今天我们就先介绍BitmaoFactory这个最常用的。
1、通过资源文件获取Bitmap(drawable/mipmap/raw)
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.dafenqi);
2、通过assets获取
//从assets中获取资源文件Bitmap bitmap = null;try {InputStream inputStream = mContext.getAssets().open("dafenqi.png");bitmap = BitmapFactory.decodeStream(inputStream);inputStream.close();} catch (IOException e) {e.printStackTrace();}
3、通过内存卡
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");
4、通过网络
// 此处省略了获取网络输入流的代码Bitmap bitmap = BitmapFactory.decodeStream(is);is.close();
5、下面我们将itmap绘制到我们的界面上
第一种方法中后两个参数(matrix, paint)是在绘制的时候对图片进行一些改变,如果只是需要将图片内容绘制出来只需要如下操作就可以了:
第二种方法就是在绘制时指定了图片左上角的坐标(距离坐标原点的距离):
注意:此处指定的是与坐标原点的距离,并非是与屏幕顶部和左侧的距离, 虽然默认状态下两者是重合的,但是也请注意分别两者的不同。
canvas.drawBitmap(bitmap,200,500,new Paint());
第三种方法比较有意思,上面多了两个矩形区域(src,dst),这两个矩形选区是干什么用的?
// 将画布坐标系移动到画布中央canvas.translate(mWidth/2,mHeight/2); //将画布的中心圆点移动到中心位置// 指定图片绘制区域(左上角的四分之一)Rect src = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);// 指定图片在屏幕上显示的区域Rect dst = new Rect(0,0,200,200);// 绘制图片canvas.drawBitmap(bitmap,src,dst,null);
详解:
上面是以绘制该图为例,用src指定了图片绘制部分的区域,即下图中红色方框标注的区域。
然后用dst指定了绘制在屏幕上的绘制,即下图中蓝色方框标注的区域,图片宽高会根据指定的区域自动进行缩放。