画布Canvas绘制基础
之前提到自定义View中的“神笔”Paint,现在来看看“画布”。Canvas就是自定义View中的“画布”,可以在Canvas上面绘制文本、Bitmap、路径、图形等,绘制设计炫酷的界面。
1、Canvas
关于Canvas更多内容详见Android Developers>Docs>Reference>Canvas。
1.1、Canvas类
Canvas在android.graphics包中,位于源码的../frameworks/base/graphics/java/android/graphics/位置。Canvas类相关的继承关系如下:
RecordingCanvas < DisplayListCanvas < BaseRecordingCanvas < Canvas< BaseCanvas
1.2、Canvas四要素
继续了解Canvas之前,需要先知道Canvas的四个基本组成要素:
①用于容纳像素的位图Bitmap a Bitmap to hold the pixels
②用于承载绘制调用的Canvas(写入位图) a Canvas to host the draw calls (writing into the bitmap)
③一个绘制基元(例如Rect,Path,文本,位图) a drawing primitive (e.g. Rect, Path, text, Bitmap)
④绘制的画笔Paint(颜色和样式) a paint (to describe the colors and styles for the drawing)
2、获取Canvas
如何获取“画布”Canvas呢?在Android开发中有几个方法,一一道来。
2.1、重写onDraw(Canvas )
自定义View的时候通常重写onDraw(Canvas )方法,传入的唯一参数就是一个Canvas实例。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}2.2、创建Canvas实例
直接通过构造函数创建Canvas,不过需要传入或者设置绘制用的Bitmap。
//创建Bitmap,Canvas必须。
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
//或者再setBitmap
Canvas canvas = new Canvas();
canvas.setBitmap(bitmap);2.3、借助SurfaceHolder
调用SurfaceHolder的lockCanvas()方法返回Canvas实例,可以在该画布上操作。
Canvas canvas1 = surfaceHolder.lockCanvas();3、Canvas绘制API
Canvas封装了大量的绘制API,光是draw***()方法就有50余种。大致分为几类,来了解一下,开发项目的时候除了靠经验记住一些,其它的都需要查阅API文档。
3.1、颜色
Canvas提供了一系列的绘制颜色的方法,关于Color详细内容见《Color详解》。
①drawColor(int color)
②drawColor(long color) API level29
③drawColor(int color, PorterDuff.Mode mode)
④drawColor(int color, BlendMode mode)
⑤drawColor(long color, BlendMode mode)
⑥drawARGB(int a, int r, int g, int b)
⑦drawRGB(int r, int g, int b)
3.2、图形类
Canvas提供了丰富的API绘制各种几何图形。点、线、矩形、圆。
3.2.1、点
①drawPoint(float x, float y,Paint paint) :绘制一个点
②drawPoints(float[] pts,Paint paint):绘制一系列点
③drawPoints(float[] pts, int offset, int count,Paint paint)
3.2.2、线
①drawLine(float startX, float startY, float stopX, float stopY,Paint paint)
②drawLines(@Size(multiple = 4)float[] pts,Paint paint):绘制一系列线条,集合中数量是4整数倍
③drawLines(float[] pts, int offset, int count,Paint paint)
/**
* 画一系列线。 每行取自pts数组中的4个连续值.
* 因此,要绘制1条线,数组必须至少包含4个值。
*
* @param pts 要绘制的点数组[x0 y0 x1 y1 x2 y2 ...]
* @param offset 绘制前要跳过的数组中的值数。
* @param count 跳过数组中offset个值后,要继续处理的数组中的值数。由于每行使用4个值,至少为4的整数倍。
* @param paint 用于画点的Paint
*/
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count, @NonNull Paint paint) {
super.drawLines(pts, offset, count, paint);
}3.2.3、椭圆/圆
①drawOval(RectF oval,Paint paint):绘制椭圆,RectF矩形的内切椭圆
②drawOval(float left, float top, float right, float bottom,Paint paint)
③drawCircle(float cx, float cy, float radius,Paint paint):绘制圆形
3.2.4、扇形
①drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)
/**
* 绘制指定的圆弧,将其缩放以适合指定的椭圆形.
* 如果起始角度为负或> = 360,则将起始角度视为以360为模的起始角度。
* @param oval 椭圆的边界,用于定义圆弧的形状和大小
* @param startAngle 弧开始的起始角度(度)
* @param sweepAngle 顺时针测量的扫描角度(度)
* @param useCenter 如果为true,则将椭圆的中心包括在圆弧中,并在对其进行描边时将其关闭。 这会画一个楔子
* @param paint 用于画弧的Paint
*/
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint) {
super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
}3.2.5、矩形
①drawRect(float left, float top, float right, float bottom,Paint paint)
②drawRect(Rect r,Paint paint):借助Rect绘制矩形
③drawRect(RectF rect, Paint paint):使用RectF绘制
④drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,Paint paint):绘制圆角矩形,最后两个参数rx、ry是围绕角落的椭圆的X、Y半径
⑤drawRoundRect(RectF rect, float rx, float ry,Paint paint)
⑥drawDoubleRoundRect(RectF outer,float[] outerRadii,RectF inner,float[] innerRadii,Paint paint):绘制内外两个矩形,数组大小8(上下左右四个角xy各两个值)
⑦drawDoubleRoundRect(RectF outer, float outerRx, float outerRy,RectF inner, float innerRx, float innerRy,Paint paint)
3.3、文字
绘制文本时,设置绘制文字的大小通过Paint的setTextSize(float textSize)方法,同时注意一般给Paint设置Style为Paint.Style.FILL_AND_STROKE,不然绘制出的文字是镂空的,当然以实际需要为准。
①drawText(String text, float x, float y,Paint paint):在Canvas中的坐标(x,y)开始绘制文本text
②drawText(String text, int start, int end, float x, float y,Paint paint):绘制text中从start(含)开始,到第end(不含)字符
③drawText(char[] text, int index, int count, float x, float y,Paint paint)
④drawText(String text, int start, int end, float x, float y,Paint paint)
⑤drawTextOnPath(String text,Path path, float hOffset,float vOffset,Paint paint):在指定的Path路径上绘制文字,比较实用的一个方法,绘制有趣的文字。
⑥drawTextOnPath(char[] text, int index, int count,Path path,float hOffset, float vOffset,Paint paint)
/**
* 根据路径去绘制文本
*
* @param text String 绘制的文本内容
* @param path 路径
* @param hOffset float 距离路径开始位置的偏移量
* @param vOffset float 距离路径上下的偏移量(可以为负数)
* @param paint 画笔对象
*/
public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
float vOffset, @NonNull Paint paint) {
super.drawTextOnPath(text, path, hOffset, vOffset, paint);
}⑦drawTextRun(char[] text, int index, int count, int contextIndex,int contextCount, float x, float y, boolean isRtl,Paint paint):高级操作,主要针对阿拉伯语RTL,详见扔物线大神HenCoder Android开发进阶:自定义 View 1-3 drawText() 文字的绘制
⑧drawTextRun(CharSequence text, int start, int end, int contextStart,int contextEnd, float x, float y, boolean isRtl,Paint paint)
⑨drawTextRun(MeasuredText text, int start, int end, int contextStart,int contextEnd, float x, float y, boolean isRtl,Paint paint)
⑩drawPosText(char[] text, int index, int count,@Size(multiple = 2) float[] pos,Paint paint):不适合复杂Text的绘制,而且不适合表情符号,所以被废弃
⑪drawPosText(String text,@Size(multiple = 2) float[] pos,Paint paint)
3.4、图像
①drawBitmap(Bitmap bitmap, float left, float top,Paint paint)
②drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint)
③drawBitmap(Bitmap bitmap,Rect src,Rect dst,Paint paint)
④drawBitmap(Bitmap bitmap,Matrix matrix,Paint paint)
3.5、Path路径
①drawPath(@NonNull Path path, @NonNull Paint paint):绘制复杂路径,关于Path以后再详细了解。
/**
* 使用指定的涂料绘制指定的路径。 路径将根据绘画中的样式填充或构图。
*
* @param path 绘制的路径
* @param paint 用于绘制路径的Paint
*/
public void drawPath(@NonNull Path path, @NonNull Paint paint) {
super.drawPath(path, paint);
}相关资料:
Android Developers > Docs > Reference > Canvas

