Android Paint Canvas Path
Canvas(画布),Paint(画笔),Path(路径) 是 android.graphics
接口类下的三个绘图 API
Paint ( 画笔 )
Paint (画笔) 用于设置绘制风格,如 线宽(笔触粗细),颜色,透明度和填充风格
获得一个 Paint
对象实例很简单
Paint paint = new Paint();
Paint 类提供了下表的方法用于设置 Paint(画笔) 的相关属性
方法 | 说明 |
---|---|
setARGB(int a,int r,int g,int b) | 设置绘制的颜色,a代表透明度,r,g,b代表颜色值 |
setAlpha(int a) | 设置绘制图形的透明度 |
setColor(int color) | 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。 |
setAntiAlias(boolean aa) | 设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢 |
setDither(boolean dither) | 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰 |
setFilterBitmap(boolean filter) | 如果该项设置为true,则图像在动画进行中会滤掉对 Bitmap 图像的优化操作,加快显示速度,本设置项依赖于 dither 和 xfermode 的设置 |
setMaskFilter(MaskFilter maskfilter) | 设置 MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等 |
setColorFilter(ColorFilter colorfilter) | 设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果 |
setPathEffect(PathEffect effect) | 设置绘制路径的效果,如点画线等 |
setShader(Shader shader) | 设置图像效果,使用Shader可以绘制出各种渐变效果 |
setShadowLayer(float radius ,float dx,float dy,int color) | 在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx 和 dy 为阴影在 x 轴和 y 轴上的距离,color 为阴影的颜色 |
setStyle(Paint.Style style) | 设置画笔的样式,为FILL,FILL_OR_STROKE,或STROKE |
setStrokeCap(Paint.Cap cap) | 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样Cap.ROUND,或方形样式Cap.SQUARE |
setSrokeJoin(Paint.Join join) | 设置绘制时各图形的结合方式,如平滑效果等 |
setStrokeWidth(float width) | 当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度 |
setXfermode(Xfermode xfermode) | 设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果 |
setFakeBoldText(boolean fakeBoldText) | 模拟实现粗体文字,设置在小字体上效果会非常差 |
setSubpixelText(boolean subpixelText) | 设置该项为true,将有助于文本在LCD屏幕上的显示效果 |
setTextAlign(Paint.Align align) | 设置绘制文字的对齐方向 |
setTextScaleX(float scaleX) | 设置绘制文字x轴的缩放比例,可以实现文字的拉伸的效果 |
setTextSize(float textSize) | 设置绘制文字的字号大小 |
setTextSkewX(float skewX) | 设置斜体文字,skewX为倾斜弧度 |
setTypeface(Typeface typeface) | 设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等 |
setUnderlineText(boolean underlineText) | 设置带有下划线的文字效果 |
setStrikeThruText(boolean strikeThruText) | 设置带有删除线的效果 |
setStrokeJoin(Paint.Join join) | 设置结合处的样子 Miter:结合处为锐角 Round:结合处为圆弧 BEVEL:结合处为直线 |
setStrokeMiter(float miter) | 设置画笔倾斜度 |
setStrokeCap(Paint.Cap cap) | 设置转弯处的风格 |
float ascent( ) | 测量baseline之上至字符最高处的距离) |
float descent() | baseline之下至字符最低处的距离 |
int breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth) | 检测一行显示多少文字 |
clearShadowLayer() | 清除阴影层 |
Canvas( 画布 )
画笔有了,接着就到画布(Canvas),总不能凭空作画是吧
创建一个 Canvas ( 画布 ) 的方法有两种
-
创建一个空的画布,可以使用 setBitmap() 方法来设置绘制具体的画布
Canvas c = Canvas();
-
以 bitmap对象创建一个画布,将内容都绘制在 bitmap 上
bitmap 不能 nullCanvas c = Canvas(Bitmap bitmap);
Canvas ( 画布 ) 提供了以下方法用来绘制,裁剪和保存画的东西
-
drawXXX()
方法族:以一定的坐标值在当前画图区域画图,另外图层会叠加, 即后面绘画的图层会覆盖前面绘画的图层方法 说明 drawRect(RectF rect, Paint paint) 绘制区域,参数一为 RectF 一个区域 drawPath(Path path, Paint paint) 绘制一个路径,参数一为 Path 路径对象 drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(这里是bitmap),参数三是目标区域(应该在canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失 drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) 画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint 画刷对象。 drawPoint(float x, float y, Paint paint) 画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象 drawText(String text, float x, floaty, Paint paint) 渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。 drawOval(RectF oval, Paint paint) 画椭圆,参数一是扫描区域,参数二为paint对象; drawCircle(float cx, float cy, float radius,Paint paint) 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象; drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象; -
clipXXX() 方法族:在当前的画图区域裁剪 (clip) 出一个新的画图区域,这个画图区域就是 canvas 对象的当前画图区域了
比如:clipRect(new Rect()),那么该矩形区域就是 canvas 的当前画图区域
-
save() 和 restore() 方法
方法 说明 save() 用来保存Canvas的状态。save之后,可以调用 Canvas 的平移、放缩、旋转、错切、裁剪等操作 restore() 用来恢复 Canvas 之前保存的状态。防止 save 后对 Canvas 执行的操作对后续的绘制有影响 save() 和 restore() 要配对使用( restore 可以比 save 少,但不能多),若restore 调用次数比 save 多,会报错
-
translate(float dx, float dy)
平移,将画布的坐标原点向左右方向移动x,向上下方向移动 y.canvas 的默认位置是在 (0,0)
-
scale(float sx, float sy)
缩放,x 为水平方向的放大倍数,y 为竖直方向的放大倍数
-
rotate(float degrees) 旋转,angle 指旋转的角度,顺时针旋转
Path(路径)
Path(路径) 简单点说就是描点,连线
创建了 Path 的实例后,可以调用 Canvas 的 drawPath(path,paint) 将图形绘制出来
Path (路径) 的常用方法如下
方法 | 说明 |
---|---|
addArc(RectF oval, float startAngle, float sweepAngle | 为路径添加一个多边形 |
addCircle(float x, float y, float radius, Path.Direction dir) | 给 Path 添加圆圈 |
addOval(RectF oval, Path.Direction dir) | 添加椭圆形 |
addRect(RectF rect, Path.Direction dir) | 添加一个区域 |
addRoundRect(RectF rect, float[] radii, Path.Direction dir) | 添加一个圆角区域 |
isEmpty() | 判断路径是否为空 |
transform(Matrix matrix) | 矩阵变换 |
transform(Matrix matrix, Path dst) | 矩阵变换并将结果存到路径 |
更高级的效果可以使用 PathEffect 类,常用方法如下
方法 | 说明 |
---|---|
moveTo(float x, float y) | 不会进行绘制,只用于移动移动画笔 |
lineTo(float x, float y) | 用于直线绘制,默认从 (0,0) 开始绘制,用 moveTo 移动。 比如 mPath.lineTo(300, 300);canvas.drawPath(mPath, mPaint); |
quadTo(float x1, float y1, float x2, float y2) | 用于绘制圆滑曲线,即贝塞尔曲线,同样可以结合 moveTo 使用 |
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) | 同样是用来实现贝塞尔曲线的。 (x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点 |
arcTo(RectF oval, float startAngle, float sweepAngle) | 绘制弧线(实际是截取圆或椭圆的一部分)ovalRectF为椭圆的矩形,startAngle 为开始角度,sweepAngle 为结束角度 |
范例
属性那么多,肯定需要一个 demo 来练练手
画图要么在 View
上画,要么在 SurfaceView
上画,我们选用 View
-
创建一个 空的 Android 项目
cn.twle.android.DrawableTool
-
自定义一个 View 类
MsView.java
package cn.twle.android.drawabletool; import android.content.Context; import android.graphics.Canvas; import android.graphics.BitmapFactory; import android.graphics.Path; import android.graphics.Color; import android.graphics.RectF; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class MsView extends View{ private Paint mPaint; public MsView(Context context) { super(context); init(); } public MsView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ mPaint = new Paint(); mPaint.setAntiAlias(true); //抗锯齿 mPaint.setColor(0xffff0000); //画笔颜色,红色 mPaint.setStyle(Paint.Style.FILL); //画笔风格 mPaint.setTextSize(36); //绘制文字大小,单位px mPaint.setStrokeWidth(5); //画笔粗细 } //重写该方法,在这里绘图 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawable(canvas); invalidate(); } public void drawable(Canvas canvas) { } }
-
修改
MainActivity.java
设置setContentView(new MsView(MainActivity.this))
package cn.twle.android.drawabletool; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MsView(MainActivity.this)); } }
接下来我们只要填充 MsView
的 drawable()
方法就可以了
-
设置画布颜色
public void drawable(Canvas canvas) { // 设置画布背景颜色 canvas.drawColor(0xFFEEEEEE); }
-
绘制圆形
public void drawable(Canvas canvas) { // 设置画布背景颜色 canvas.drawColor(0xFFEEEEEE); // 画实心圆 canvas.drawCircle(200, 200, 100, mPaint); }
-
绘制矩形
public void drawable(Canvas canvas) { // 设置画布背景颜色 canvas.drawColor(0xFFEEEEEE); // 画矩形 canvas.drawRect(100, 100, 300, 200, mPaint); }
-
绘制 Bitmap
public void drawable(Canvas canvas) { // 绘制 Bitmap canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher), 100, 100, mPaint); }
-
绘制弧形区域
public void drawable(Canvas canvas) { // 绘制弧形区域 canvas.drawArc(new RectF(100, 100, 200, 200),0,90,true,mPaint); }
假如 true 改为 false
public void drawable(Canvas canvas) { // 绘制弧形区域 canvas.drawArc(new RectF(100, 100, 200, 200),0,90,false,mPaint); }
-
绘制圆角矩形
public void drawable(Canvas canvas) { // 画圆角矩形 canvas.drawRoundRect(new RectF(10,10,210,110),15,15,mPaint); }
-
绘制椭圆
public void drawable(Canvas canvas) { // 画椭圆 canvas.drawOval(new RectF(10,10,200,300),mPaint); }
-
绘制多边形
public void drawable(Canvas canvas) { Path path = new Path(); path.moveTo(10, 10); //移动到 坐标10,10 path.lineTo(100, 50); path.lineTo(200,40); path.lineTo(300, 20); path.lineTo(200, 10); path.lineTo(100, 70); path.lineTo(50, 40); path.close(); canvas.drawPath(path,mPaint); }
-
绘制文字
public void drawable(Canvas canvas) { //绘制文字 canvas.drawText("简单教程,简单编程",50,50,mPaint); }
-
沿着某条 Path 来绘制这些文字
public void drawable(Canvas canvas) { Path path = new Path(); path.moveTo(50,50); path.lineTo(100, 100); path.lineTo(300, 200); path.lineTo(400, 400); path.close(); // 绘制文字 canvas.drawTextOnPath("简单教程,简单编程", path, 50, 50, mPaint); }
-
绘制自定义的图形
public void drawable(Canvas canvas) { //将位置移动画纸的坐标点:150,150 canvas.translate(150, 150); mPaint.setColor(0xffffffff); //画圆圈 canvas.drawCircle(0, 0, 100, mPaint); mPaint.setColor(0xffff0000); //使用 Path 绘制路径文字 canvas.save(); canvas.translate(-75, -75); Path path = new Path(); path.addArc(new RectF(0,0,150,150), -180, 180); Paint citePaint = new Paint(mPaint); citePaint.setTextSize(14); citePaint.setStrokeWidth(1); canvas.drawTextOnPath("简单教程,简单编程", path, 28, 0, citePaint); canvas.restore(); //小刻度画笔对象 Paint tmpPaint = new Paint(mPaint); tmpPaint.setStrokeWidth(1); float y=100; int count = 60; //总刻度数 for(int i=0 ; i <count ; i++){ if(i%5 == 0){ canvas.drawLine(0f, y, 0, y+12f, mPaint); canvas.drawText(String.valueOf(i/5+1), -4f, y+25f, tmpPaint); }else{ canvas.drawLine(0f, y, 0f, y +5f, tmpPaint); } //旋转画纸 canvas.rotate(360/count,0f,0f); } // 绘制指针 tmpPaint.setColor(Color.GRAY); tmpPaint.setStrokeWidth(4); canvas.drawCircle(0, 0, 7, tmpPaint); tmpPaint.setStyle(Paint.Style.FILL); tmpPaint.setColor(Color.YELLOW); canvas.drawCircle(0, 0, 5, tmpPaint); canvas.drawLine(0, 10, 0, -65, mPaint); }