完全自定义控件-Canvas之绘制基本形状
2016-08-23 本文已影响1924人
hongjay
一.简介
Canvas 美[ˈkænvəs] 画布
Canvas绘图有三个基本要素:Canvas、绘图坐标系以及Paint。
- Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint。
- drawXXX方法以及传入其中的坐标决定了要绘制的图形的形状,比如drawCircle方法,用来绘制圆形,需要我们传入圆心的x和y坐标,以及圆的半径。
- drawXXX方法中传入的画笔Paint决定了绘制的图形的一些外观,比如是绘制的图形的颜色,再比如是绘制圆面还是圆的轮廓线等。
- Canvas的drawXXX方法中传入的各种坐标指的都是绘图坐标系中的坐标。在初始状况下,绘图坐标系的坐标原点在View的左上角。
但绘图坐标系可以改变,例如translate方法,可以平移坐标系。且坐标系的位移是基于当前位置移动,而不是每次基于屏幕左上角的(0,0)点移动。
二.Canvas的常用操作速查表
操作类型 | 相关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比较难以理解和使用,故封装了一些常用的方法。 |
三.实战
绘制颜色 drawARGB:
绘制颜色是填充整个画布,常用于绘制底色。
- 新建CanvasView类继承View
- 重写onDraw
public class CanvasView extends View {
//在代码中定义和使用时用到的
public CanvasView(Context context) {
super(context);
}
//在xml中定义我们的自定义属性时用到
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
}
//在View中画出我们需要的内容
@Override
protected void onDraw(Canvas canvas) {
canvas.drawARGB(255, 139, 197, 186);
}
}
绘制画布
绘制点 drawPoint:
- 在构造函数中初始化画笔
- 重写onDraw
public class CanvasView extends View {
private Paint mPaint;
//在代码中定义和使用时用到的
public CanvasView(Context context) {
super(context);
init();
}
//在xml中定义我们的自定义属性时用到
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//在构造函数中初始化画笔
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.BLACK); //设置画笔颜色
mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充
mPaint.setStrokeWidth(10f); //设置画笔宽度为10px
}
//在View中画出我们需要的内容
@Override
protected void onDraw(Canvas canvas) {
canvas.drawPoint(100, 100, mPaint); //在坐标(100,100)位置绘制一个点
canvas.drawPoints(new float[]{ //绘制一组点,坐标位置由float数组指定
200, 200,
300, 400,
400, 500
}, mPaint);
}
}
绘制点
绘制直线 drawLine:
protected void onDraw(Canvas canvas) {
mPaint.setColor(Color.GREEN);// 设置绿色
canvas.drawLine(60, 40, 100, 40, mPaint);// 画线
canvas.drawLine(110, 40, 190, 80, mPaint);// 斜线
canvas.drawLines(new float[]{ // 绘制一组线 每四数字(两个点的坐标)确定一条线
100,200,200,200,
100,300,200,300
},mPaint);
}
绘制直线
绘制矩形 drawRect:
确定确定一个矩形最少需要四个数据,就是对角线的两个点的坐标值,这里一般采用左上角和右下角的两个点的坐标。
protected void onDraw(Canvas canvas) {
//取得画布的宽高
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
//设置画笔的填充色是蓝色
mPaint.setColor(Color.BLUE);
int left1 = 10;
int top1 = 10;
int right1 = canvasWidth / 3;
int bottom1 = canvasHeight /3;
canvas.drawRect(left1, top1, right1, bottom1, mPaint);
//修改画笔颜色
mPaint.setColor(Color.RED);
int left2 = canvasWidth / 3 * 2;
int top2 = 10;
int right2 = canvasWidth - 10;
int bottom2 = canvasHeight / 3;
canvas.drawRect(left2, top2, right2, bottom2, mPaint);
}
- 简单画了下法国国旗
绘制圆角矩形 drawRoundRect:
protected void onDraw(Canvas canvas) {
mPaint.setColor(0xff8bc5ba);//A:ff,R:8b,G:c5,B:ba
RectF rectF = new RectF(10,10,300,150);
//这里的圆弧是椭圆的圆弧,所以要设置椭圆的两个半径
canvas.drawRoundRect(rectF,10,10,mPaint);
}
rx,ry
绘制圆角矩形
绘制圆、圆环和椭圆 drawCircle、drawOval:
protected void onDraw(Canvas canvas) {
mPaint.setColor(0xff8bc5ba);
mPaint.setAntiAlias(true); //设置画笔为抗锯齿模式,不然画出来太丑了
mPaint.setStyle(Paint.Style.FILL);//默认绘图为填充模式
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
int halfCanvasWidth = canvasWidth / 2;
int R = canvasHeight / 9;
// 绘制一个矩形的内切椭圆
RectF rectF = new RectF(100, 10, 370, 150);
canvas.drawOval(rectF, mPaint);
// 绘制一个圆心坐标在(halfCanvasWidth,250),半径为R 的圆
canvas.drawCircle(halfCanvasWidth, 250, R, mPaint);
//通过绘制两个圆形成圆环
//1. 首先绘制大圆
canvas.drawCircle(halfCanvasWidth, 450, R, mPaint);
//2. 然后绘制小圆,让小圆覆盖大圆,形成圆环效果
int r = (int) (R * 0.75);
mPaint.setColor(0xffffffff);//将画笔设置为白色,画小圆
canvas.drawCircle(halfCanvasWidth, 450, r, mPaint);
//通过画笔的描边绘图模式绘制圆环
mPaint.setColor(0xff8bc5ba);//设置颜色
mPaint.setStyle(Paint.Style.STROKE);//绘图为描边模式
float strokeWidth = (float) (R * 0.25); //设置线条宽度
mPaint.setStrokeWidth(strokeWidth);
canvas.drawCircle(halfCanvasWidth, 650, R, mPaint);
}
绘制圆、圆环、椭圆
- 简要介绍Paint的模式
- STROKE 描边,把边给填充颜色
- FILL 填充,填充边中的内容
- FILL_AND_STROKE 描边加填充,就是把上面两个合起来
绘制圆弧 drawArc:
Canvas中提供了drawArc方法用于绘制弧,这里的弧指两种:弧面和弧线,弧面即用弧围成的填充面,弧线即为弧面的轮廓线。
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
- oval是RecF类型的对象,其定义了椭圆的形状。
- startAngle指的是绘制的起始角度,如果传入的startAngle小于0或者大于等于360,那么用startAngle对360进行取模后作为起始绘制角度。
- sweepAngle指的是从startAngle开始沿着钟表的顺时针方向旋转扫过的角度。如果sweepAngle大于等于360,那么会绘制完整的椭圆弧。如果sweepAngle小于0,那么会用sweepAngle对360进行取模后作为扫过的角度。
- useCenter是个boolean值,如果为true,表示在绘制完弧之后,用椭圆的中心点连接弧上的起点和终点以闭合弧;如果值为false,表示在绘制完弧之后,弧的起点和终点直接连接,不经过椭圆的中心点。
protected void onDraw(Canvas canvas) {
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
//把画布分成五份
float ovalHeight = canvasHeight / 5;
float left = 10 ;
float top = 0;
float right = canvasWidth - left;
float bottom= ovalHeight;
RectF rectF = new RectF(left, top, right, bottom);
mPaint.setAntiAlias(true); //抗锯齿
mPaint.setStrokeWidth(5);//设置线宽
mPaint.setColor(0xff8bc5ba);//设置颜色
mPaint.setStyle(Paint.Style.FILL);//默认设置画笔为填充模式
//绘制用drawArc绘制完整的椭圆
canvas.drawArc(rectF, 0, 360, true, mPaint);
//绘制椭圆的四分之一,起点是0度,到90度
canvas.translate(0, ovalHeight ); //绘图坐标系平移操作,x轴移动0,y轴移动五分之一个画布长度
canvas.drawArc(rectF, 0, 90, true, mPaint);
//绘制椭圆的四分之一,将useCenter设置为false
canvas.translate(0, ovalHeight );
canvas.drawArc(rectF, 0, 90, false, mPaint);
//绘制椭圆的四分之一,只绘制轮廓线
mPaint.setStyle(Paint.Style.STROKE);//设置画笔为描边模式
canvas.translate(0, ovalHeight );
canvas.drawArc(rectF, 0, 90, true, mPaint);
//绘制带有轮廓线的椭圆的四分之一
//1. 先绘制椭圆的填充部分
mPaint.setStyle(Paint.Style.FILL);//设置画笔为填充模式
canvas.translate(0, ovalHeight );
canvas.drawArc(rectF, 0, 90, true, mPaint);
//2. 再绘制椭圆的轮廓线部分
mPaint.setStyle(Paint.Style.STROKE);//设置画笔为线条模式
mPaint.setColor(0xff0000ff);//设置轮廓线条为蓝色
canvas.drawArc(rectF, 0, 90, true, mPaint);
}
绘制圆弧
自定义饼图:
学了那么大堆基础终于可以画个能用的图了
自定义饼图protected void onDraw(Canvas canvas) {
RectF rectF = new RectF(100, 100, 400, 400);
mPaint.setAntiAlias(true); //抗锯齿
mPaint.setStrokeWidth(5);//设置线宽
mPaint.setColor(0xFFCCFF00);//设置颜色
mPaint.setStyle(Paint.Style.FILL);//默认设置画笔为填充模式
canvas.drawArc(rectF, 0, 110, true, mPaint);
mPaint.setColor(0xff8bc5ba);//设置颜色
canvas.drawArc(rectF, 110, 50, true, mPaint);
mPaint.setColor( 0xFF800000);//设置颜色
canvas.drawArc(rectF, 160, 80, true, mPaint);
mPaint.setColor(0xFFFF8C69);//设置颜色
canvas.drawArc(rectF, 240, 120, true, mPaint);
}
这里是项目地址
参考
http://blog.csdn.net/iispring/article/details/49770651
https://github.com/GcsSloop/AndroidNote/blob/master/CustomView/Advance/%5B02%5DCanvas_BasicGraphics.md