Android图形处理-Canvas
Canvas
Canvas绘图有三个基本要素:Canvas、绘图坐标系以及Paint。Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint.
两个坐标系
- canvas坐标系是固定的
- 画图坐标系可以移动:可以通过调用Canvas的translate方法平移坐标系,可以通过Canvas的rotate方法旋转坐标系,真正对我们绘图有用的是绘图坐标系而非Canvas坐标系。
常见方法
drawARGB
Canvas中的drawARGB可以用来对整个Canvas以某种统一的颜色整体绘制,四个参数分别是Alpha、Red、Green、Blue,取值都是0-255
就是相当于填充的作用
drawText
Android中的画笔有两种Paint和TextPaint,我们可以Paint来画其他的图形:点、线、矩形、椭圆等。TextPaint继承自Paint,是专门用来画文本的,由于TextPaint继承自Paint,所以也可以用TextPaint画点、线、面、矩形、椭圆等图形
画笔Paint控制着所绘制的图形的具体外观,Paint默认的字体大小为12px,在绘制文本时我们往往要考虑密度density设置合适的字体大小。画笔的默认颜色为黑色,默认的style为FILL,默认的cap为BUTT,默认的线宽为0
drawPoint
就是一个设置point(点)的形状:
//绘制Cap为ROUND的点
paint.setStrokeCap(ROUND);
canvas.drawPoint(x, y, paint);
drawRect
Rect rect = new Rect(0, 10, 50, 60);
canvas.drawRect(rect,paint);
rect的四个参数分别是left,top,right,bottom
drawCircle
canvas.drawCircle(200,200,50,paint);
就是圆心的坐标和半径
画出一个环
有两个思路一个是画出来两个圆,另外一个是设置画笔的模式:
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
Paint通过setStyle方法设置要绘制的类型,style有取三种值:Paint.Style.FILL、Paint.Style.STROKE和Paint.Style.FILL_AND_STROKE。
- 当style为FILL时,绘制是填充面,FILL是Paint默认的style;
- 当style为STROKE时,绘制的是图形的轮廓线;
- 当style为FILL_AND_STROKE时,同时绘制填充面和轮廓线,不过这种情况用的不多,因为填充面和轮廓线是用同一种颜色绘制的,区分不出轮廓线的效果。
drawOval
注意椭圆使用的是RectF不是Rect,画出一个空心椭圆:
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
RectF rectF = new RectF(0, 10, 150, 90);
canvas.drawOval(rectF, paint);
画出一个带有轮廓的椭圆:
本质就是画出两个椭圆:
// 画出内部
paint.setStrokeWidth(5);
RectF rectF = new RectF(0, 10, 150, 90);
canvas.drawOval(rectF, paint);
// 画出外部轮廓
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLUE);
canvas.drawOval(rectF, paint);
drawText具体使用
在绘制字体之前一定要先移动canvas否则会盖住字体
绘制正常文字
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(50);
canvas.save();
canvas.translate(0, 50);
canvas.drawText("你好", 0, 0, paint);
canvas.restore();
注意canvas.translate(0, 50)要先平移画布
canvas.drawText(“你好”, 0, 0, paint)两个整形参数分别代表的是在水平和垂直方向的偏移量
绘制带有对齐方向的文字
paint.setTextAlign(Paint.Align.LEFT)设置文字对齐的方向
注意这里的居中对齐是整个文字的中间正好在绘图坐标的原点
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(50);
paint.setTextAlign(Paint.Align.CENTER);
canvas.save();
// canvas.translate(width/2, 50);
canvas.translate(0, 50);
canvas.drawText("你好", 0, 0, paint);
canvas.restore();
这种情况绘制出只有一个字:
而要显示出你,就是先移动坐标系:
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(50);
paint.setTextAlign(Paint.Align.CENTER);
canvas.save();
canvas.translate(width/2, 50);
// canvas.translate(0, 50);
canvas.drawText("你好", 0, 0, paint);
canvas.restore();
就是你好的中间正好是绘图的坐标原点
所以绘制右对齐要先向右移动一个画布的距离:
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(50);
paint.setTextAlign(Paint.Align.RIGHT);
canvas.save();
canvas.translate(width, 50);
// canvas.translate(0, 50);
canvas.drawText("你好", 0, 0, paint);
canvas.restore();
这几个启动的核心是相对于字体而言的,就是居中对齐就找字体的中间,右对齐就找字体的右侧,而永远对齐画布的左侧
绘制带有下划线和加粗的字体
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setTextSize(50);
paint.setTextAlign(Paint.Align.LEFT);
// 设置下划线
paint.setUnderlineText(true);
// 设置加粗
paint.setFakeBoldText(true);
canvas.save();
// canvas.translate(width, 50);
canvas.translate(0, 50);
canvas.drawText("你好", 0, 0, paint);
canvas.restore();
drawArc具体使用
public void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
- oval是RecF类型的对象,其定义了椭圆的形状。
- startAngle指的是绘制的起始角度,钟表的3点位置对应着0度,如果传入的startAngle小于0或者大于等于360,那么用startAngle对360进行取模后作为起始绘制角度。
- sweepAngle指的是从startAngle开始沿着钟表的顺时针方向旋转扫过的角度。如果sweepAngle大于等于360,那么会绘制完整的椭圆弧。如果sweepAngle小于0,那么会用sweepAngle对360进行取模后作为扫过的角度。
- useCenter是个boolean值,如果为true,表示在绘制完弧之后,用椭圆的中心点连接弧上的起点和终点以闭合弧;如果值为false,表示在绘制完弧之后,弧的起点和终点直接连接,不经过椭圆的中心点。
drawOval方法可以看做是drawArc方法的一种特例
画出一个椭圆
drawArc可以和drawOval一样都能够画出一个椭圆
RectF rectF = new RectF(0, 10, 150, 90);
canvas.drawArc(rectF, 0, 360, true, paint);
注意开始的角度是水平向右,方向是顺时针
画出任意角度的椭圆
RectF rectF = new RectF(0, 10, 150, 90);
canvas.drawArc(rectF, -20, 60, true, paint);
画出一个椭圆的外部弧
RectF rectF = new RectF(0, 10, 150, 90);
canvas.drawArc(rectF, -20, 60, false, paint);
只是把useCenter设置为false,注意第一个参数是开始角度,第二个参数是跨国角度
只是画出轮廓线
在上面的代码中更新设置画笔的样式:
paint.setStyle(Paint.Style.STROKE);
RectF rectF = new RectF(0, 10, 150, 90);
canvas.drawArc(rectF, -20, 60, false, paint);
drawPath具体使用
在Android中,Path是一种线条的组合图形,其可以由直线、二次曲线、三次曲线、椭圆的弧等组成。Path既可以画线条,也可以画填充面
使用path画出图形
首先要设置画笔是填充模式Paint.Style.FILL然后在调用addXX方法画出各种形状
paint.setStyle(Paint.Style.FILL);
// 添加椭圆
RectF rectF = new RectF(0, 10, 150, 90);
Path path = new Path();
path.addOval(rectF, Path.Direction.CCW);
// 添加圆
path.addCircle(220,50,50, Path.Direction.CCW);
// 添加矩形
RectF rect = new RectF(300, 20, 400, 120);
path.addRect(rect, Path.Direction.CCW);
canvas.drawPath(path,paint);
画出空心的图形
只要在上面的代码中更改一点:
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
画出任意弧度
注意画直线的时候要先moveTo然后在lineTo
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
Path path = new Path();
// 画出一段直线
path.moveTo(0, 0);
path.lineTo(100, 50);
// 添加一个四分之一的圆弧,当两个点没有连接上的时候,系统会自动创建一个直线连接
RectF rectF = new RectF(20, 50, 180, 130);
path.arcTo(rectF, 270, 90);
path.lineTo(270, 90);
// 画出一个二阶贝塞尔曲线
path.moveTo(270, 90);
path.quadTo(80, 180, 500, 500);
canvas.drawPath(path, paint);
drawBitmap
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.love);
canvas.drawBitmap(bitmap, 0, 0, paint);
// canvas.drawBitmap(bitmap,0,0,paint);
Rect srcRect = new Rect();
srcRect.left = 0;
srcRect.right = bitmap.getWidth();
srcRect.top = 0;
srcRect.bottom = (int) (0.33 * bitmap.getHeight());
//dstRecF定义了要将绘制的Bitmap拉伸到哪里
RectF dstRecF = new RectF();
dstRecF.left = bitmap.getWidth();
dstRecF.right = canvas.getWidth();
dstRecF.top = bitmap.getHeight();
dstRecF.bottom = bitmap.getHeight() * 2;
canvas.drawBitmap(bitmap, srcRect, dstRecF, paint);
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
该方法除了传入bitmap对象外,还需要传入left和top,left和top组成了一个坐标,决定了在Canvas中从哪个地方绘制Bitmap。在我们的代码中,left和top都设置为0,所以我们就在Canvas的左上角绘制了bitmap。
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
该方法有两个功能:1.只绘制原有bitmap对象的一部分,2.还可以将要绘制的bitmap缩放到指定的区域。