Android笔记 自定义View(六):Canvas使用之绘制图片

您所在的位置:网站首页 Android自定义view难吗 Android笔记 自定义View(六):Canvas使用之绘制图片

Android笔记 自定义View(六):Canvas使用之绘制图片

2023-12-15 09:08| 来源: 网络整理| 查看: 265

本章看下Canvas绘制位图相关内容

目录

一、绘制位图(drawBitmap)

​二、绘制矢量图(drawPicture)

三、总结 

一、drawBitmap

绘制bitamp方法说明:

/* * @param * bitmap 位图 * left 绘制区域距离左边界偏移量 * top 绘制区域距离上边界偏移量 * paint 画笔 * 在View中指定位置绘制bitmap * 注:传入的参数中的偏移量是指对于View的偏移。 */ public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) /* * @param * bitmap 位图 * src bitmap需要绘制的面积,若src的面积小于bitmap时会对bitmap进行裁剪, * 一般来说需要绘制整个bitmap时可以为null * dst 在画布中指定绘制bitmap的位置,当这个区域的面积与bitmap要显示的面积不匹配时, * 会进行缩放,不可为null * paint 画笔 * 在指定位置绘制指定大小的bitmap */ public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, @Nullable Paint paint) public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint) /* * @param * bitmap 位图 * matrix 当绘制位图时需要转变时使用的矩阵 * paint 画笔 * 使用指定的矩阵绘制位图 */ public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)

java代码:

public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setLayerType(LAYER_TYPE_SOFTWARE,null); mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.you); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画出原图像 canvas.drawBitmap(mBitmap, 0, 0, null); // 指定图片绘制区域(左上角的四分之一) Rect src = new Rect(0,0,mBitmap.getWidth()/2,mBitmap.getHeight()/2); // 指定图片在屏幕上显示的区域(原图大小) Rect dst = new Rect(mBitmap.getWidth()+50,0,mBitmap.getWidth()+50+mBitmap.getWidth(),mBitmap.getHeight()); canvas.drawBitmap(mBitmap, src,dst,null); }

效果:

drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)方法是通过矩阵对图片进行一些变换处理。如下:

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画出原图像 canvas.drawBitmap(mBitmap, 0, 0, null); Matrix matrix = new Matrix(); matrix.postScale(0.5f, 0.5f); canvas.drawBitmap(mBitmap, matrix,null); }

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画出原图像 canvas.drawBitmap(mBitmap, 0, 0, null); Matrix matrix = new Matrix(); matrix.postTranslate(100f, 100f); canvas.drawBitmap(mBitmap, matrix,null); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画出原图像 canvas.drawBitmap(mBitmap, 0, 0, null); Matrix matrix = new Matrix(); matrix.postRotate(90, mBitmap.getWidth()*0.5f,mBitmap.getHeight()*0.5f); canvas.drawBitmap(mBitmap, matrix,null); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画出原图像 canvas.drawBitmap(mBitmap, 0, 0, null); Matrix matrix = new Matrix(); matrix.postSkew(0.5f,0.5f); canvas.drawBitmap(mBitmap, matrix,null); }

以上是Matrix的一些简单变换操作。它的原理比较复杂,后面在详细说明。

二、drawPicture

在Canvas中还有一类绘制图片的方法,如下:

/* * 在绘制图片之前保存Canvas状态,绘制完成之后回复Canvas */ public void drawPicture(@NonNull Picture picture) /* * 在指定区域内绘制图片,当图片大小不匹配时进行适当的缩放 */ public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) public void drawPicture(@NonNull Picture picture, @NonNull Rect dst)

从上面可以看出关键参数Picture,下面我们来说下Picture类,看下官方文档对其的解释:

A Picture records drawing calls (via the canvas returned by beginRecording) and can then play them back into Canvas (via draw(Canvas) ordrawPicture(Picture)).For most content (e.g. text, lines, rectangles), drawing a sequence from a picture can be faster than the equivalent API calls, since the picture performs its playback without incurring any method-call overhead.

上面的解释没有懂,我直接百度到的解释大概意思是:Picture和录像功能是类似的,只不过Picture录的是Canvas中绘制的内容。我们把Canvas绘制点,线,矩形等诸多操作用Picture录制下来,下次需要的时候拿来就能用,使用Picture相比于再次调用绘图API,开销是比较小的,也就是说对于重复的操作可以更加效率。

PS:可以把Picture看作是一个录制Canvas操作的录像机。下面在看下Picture的相关方法。

相关方法简介public int getWidth ()获取宽度public int getHeight ()获取高度public Canvas beginRecording (int width, int height)开始录制 (返回一个Canvas,在Canvas中所有的绘制都会存储在Picture中)public void endRecording ()结束录制public void draw (Canvas canvas)将Picture中内容绘制到Canvas中

上面表格中基本上已经列出了Picture的主要方法,我们主要看下后面三个方法:很明显,beginRecording 和 endRecording 是成对使用的,一个开始录制,一个是结束录制,两者之间的操作将会存储在Picture中。然后通过draw()方法将Picture保存的操作绘制出来。也就是说在自定义View中使用drawPicture()方法要分为两个步骤:

第一步:使用Picture录制内容 public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //注意:关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE,null); mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.you); mPicture = new Picture(); recording(); } //录制内容 private void recording() { Canvas canvas = mPicture.beginRecording(500, 500); canvas.drawBitmap(mBitmap, 0, 0, null); mPicture.endRecording(); } 第二步:将录制的内容显示出来(三种方式)

将Picture录制的内容显示出来有主要有三种方式:

方式说明1、mPicture.draw(canvas)使用Picture提供的draw方法绘制。2、canvas.drawPicture(mPicture)使用Canvas提供的drawPicture方法绘制。3、pictureDrawable.draw(canvas);将Picture包装成为PictureDrawable,使用PictureDrawable的draw方法绘制。

我们来分别看下使用情况:

1、mPicture.draw(canvas):

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPicture.draw(canvas); }

通过官方文档对这个方法的说明,我们发现在21之前的版本使用时会对Canvas的状态有影响(Matrix clip等),而且对绘制结果可控性较弱。具体的影响是什么我也没有搞明白。总之,一般不去使用它,推荐使用后面两种方式。

2、canvas.drawPicture(mPicture):

这种方式Canvas提供三个重载方法,就是我们上面列出的:

public void drawPicture (Picture picture) public void drawPicture (Picture picture, Rect dst) public void drawPicture (Picture picture, RectF dst)

我们看下效果:

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPicture(mPicture); canvas.drawPicture(mPicture,new RectF(0, 0, 300, 300)); }

发现后面两个重载方法会对图片进行缩放。Rect dst指定图片显示的区域,只不过精度不同。

3、pictureDrawable.draw(canvas):

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 包装成为Drawable PictureDrawable drawable = new PictureDrawable(mPicture); // 设置绘制区域 -- 注意此处所绘制的内容不匹配时, // 只会显示一部分,不会对picture进行裁剪 drawable.setBounds(0,0,200,mPicture.getHeight()); // 绘制 drawable.draw(canvas); }

效果图:

三、总结 

本篇介绍了Canvas绘制图片的相关内容,其中涉及到Matrix没有做深入了解。其实对于图片的复杂操作都是利用Matrix来实现的,后面会单独介绍Matrix相关内容。

祝:工作顺利!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3