参考资料:http://www.gcssloop.com/customview/Canvas_Convert
操作类型 | 相关API | 备注 |
---|---|---|
绘制颜色 | drawColor, drawRGB, drawARGB | 使用单一颜色填充整个画布 |
绘制基本形状 | drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc | 依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
绘制图片 | drawBitmap, drawPicture | 绘制位图和图片 |
绘制文本 | drawText, drawPosText, drawTextOnPath | 依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
绘制路径 | drawPath | 绘制路径,绘制贝塞尔曲线时也需要用到该函数 |
顶点操作 | drawVertices, drawBitmapMesh | 通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用 |
画布剪裁 | clipPath, clipRect | 设置画布的显示区域 |
画布快照 | save, restore, saveLayerXxx, restoreToCount, getSaveCount | 依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 |
画布变换 | translate, scale, rotate, skew | 依次为 位移、缩放、 旋转、错切 |
Matrix(矩阵) | getMatrix, setMatrix, concat | 实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 |
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
super.drawLine(startX, startY, stopX, stopY, paint);
}
第一个参数startX:起始端点的X坐标。
第二个参数startY:起始端点的Y坐标。
第三个参数 stopX:终止端点的X坐标。
第四个参数stopY:终止端点的Y坐标。
第五个参数 paint:绘制直线所使用的画笔。
@Override
protected void onDraw(Canvas canvas) {
canvas.drawLine(100,100,100,200,paint);
}
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint) {
super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
}
第一个参数oval :RectF对象设置定义圆弧的形状和大小的范围
// 这是一个居中的圆
float x=(getWidth()-getHeight()/2)/2;
float y=getHeight()/4;
RectF rectF=new RectF(x,y,getWidth()-x,getHeight()-y);
第二个参数startAngle:设置圆弧是从哪个角度来顺时针绘画的
第三个参数sweepAngle:设置圆弧扫过的角度
第四个参数useCenter:绘制圆弧时是否将圆心包括在内一起绘制
@Override
protected void onDraw(Canvas canvas) {
float x=(getWidth()-getHeight()/2)/2;
float y=getHeight()/4;
RectF rectF=new RectF(x,y,getWidth()-x,getHeight()-y);
canvas.drawArc(rectF,180,140,false,paint);
}
@Override
protected void onDraw(Canvas canvas) {
float x=(getWidth()-getHeight()/2)/2;
float y=getHeight()/4;
RectF rectF=new RectF(x,y,getWidth()-x,getHeight()-y);
canvas.drawArc(rectF,180,140,true,paint);
}
第五个参数paint: 使用的画笔
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
paint.setTextSize(dp2px(20));
paint.setStrokeWidth(10);
获取Bitmap方式:
通过Bitmap创建 :复制一个已有的Bitmap(新Bitmap状态和原有的一致) 或者 创建一个空白的Bitmap(内容可改变)
通过BitmapDrawable获取 : 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap
通过BitmapFactory获取 :从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap
通过BitmapFactory从不同位置获取Bitmap:
资源文件(drawable/mipmap):
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.checkmark);
资源文件(assets):
Bitmap bitmap=null;
try {
InputStream is = mContext.getAssets().open("bitmap.png");
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
内存卡文件:
Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");
网络文件:
// 此处省略了获取网络输入流的代码
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();
绘制Bitmap:
drawBitmap的常用方法
第一种方法中后两个参数(matrix, paint)是在绘制的时候对图片进行一些改变
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.timg);
canvas.drawBitmap(bitmap,new Matrix(),null);
第二种方法就是在绘制时指定了图片左上角的坐标(距离坐标原点的距离):
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.timg);
canvas.drawBitmap(bitmap,200,400,null);
第三种方法,上面多了两个矩形区域(src,dst)
Rect src : 指定绘制图片的区域
Rect dst 或RectF dst : 指定图片在屏幕上显示(绘制)的区域
从上面可知,第三种方法可以绘制图片的一部分到画布上,这有什么用呢?
如果你看过某些游戏的资源文件,你可能会看到如下的图片(图片来自网络):
用一张图片包含了大量的素材,在绘制的时候每次只截取一部分进行绘制,这样可以大大的减少素材数量,而且素材管理起来也很方便。
然而这和我们有什么关系呢?我们又不做游戏开发。
确实,我们不做游戏开发,但是在某些时候我们需要制作一些炫酷的效果,这些效果因为太复杂了用代码很难实现或者渲染效率不高。这时候很多人就会想起帧动画,将动画分解成一张一张的图片然后使用帧动画制作出来,这种实现方式的确比较简单,但是一个动画效果的图片有十几到几十张,一个应用里面来几个这样炫酷的动画效果就会导致资源文件出现一大堆,想找其中的某一张资源图片简直就是灾难啊有木有。但是把同一个动画效果的所有资源图片整理到一张图片上,会大大的减少资源文件数量,方便管理,妈妈再也不怕我找不到资源文件了,同时也节省了图片文件头、文件结束块以及调色板等占用的空间。
下面是利用drawBitmap第三种方法制作的一个简单示例:
Demo链接
注:这里参考链接 http://www.gcssloop.com/customview/Canvas_PictureText