Android高级进阶——绘图篇(一)Canvas基本操作
开篇
前面在介绍 onDraw 过程时,有提到 View 的绘制(Canvas 的使用),后续的几篇会详细的介绍有关 Canvas 以及 Paint 的相关操作。
Canvas 和 Paint
Canvas 和 Paint 之间的关系就像我们平时画画需要的画笔和画纸一样,我们画画无外乎也就需要这两个工具,而这两个工具体现在 Android 中,就是我们的 Paint(画笔)和 Canvas(画纸,通常称为画布),所以凡是跟要画的东西设置相关的,比如颜色、大小、宽度、样式、透明度等都是在 Paint 中设置的。而凡是跟要画的成品,比如想画一个矩形、圆形、文字、路径等都是通过 Canvas 操作的。
Canvas 的基本操作
- 新建一个类,派生自 View,重写 View 的 onDraw 方法,在 onDraw 方法中通过 Canvas 来实现我们想要实现的效果:
public class CustomView extends View {
private Paint paint;
public CustomView(Context context) {
super(context);
init();
}
private void init() {
//初始化画笔
paint = new Paint();
//设置抗锯齿
paint.setAntiAlias(true);
//设置画笔宽度
paint.setStrokeWidth(5);
//设置画笔颜色
paint.setColor(Color.RED);
//设置画笔样式
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
- 然后在布局文件中使用我们的自定义View:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android”
xmlns:app="http://schemas.android.com/apk/res-auto”
xmlns:tools="http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”
tools:context=“com.example.hecom.annotationlibrary.MainActivity”>
<com.example.hecom.annotationlibrary.CustomView
android:layout_width=“match_parent”
android:layout_height="match_parent” />
</LinearLayout>
- 画就行了
1、使用 Canvas 画圆
void drawCircle (float cx, float cy, float radius, Paint paint)
参数:
- cx:圆心点的 X 轴坐标
- cy:圆心点的 Y 轴坐标
- radius:圆的半径
- paint:画笔
private void init() {
//初始化画笔
paint = new Paint();
//设置抗锯齿
paint.setAntiAlias(true);
//设置画笔宽度
paint.setStrokeWidth(5);
//设置画笔颜色
paint.setColor(Color.RED);
//设置画笔样式
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(300,300,100,paint);
}

2、使用 Canvas 画矩形
void drawRect (float left, float top, float right, float bottom, Paint paint)
void drawRect (RectF rect, Paint paint)
void drawRect (Rect r, Paint paint)
参数:
- 第一种写法是直接传入矩形的四个点的位置,画出矩形
- 第二种写法是根据传入的 RectF 以及 Rect 矩形变量来指定所画的矩形
- 矩形工具类 RectF 与 Rect
这两个都是矩形辅助类,区别不大,用哪个都可以,根据四个点构建一个矩形结构,在画图时,利用这个矩形结构可以画出对应的矩形或者与其他图形 Region 相交、相加等- RectF
构造函数有四个,但最常用的还是第二个,根据四个点构造出一个矩形
RectF()
RectF(float left, float top, float right, float bottom)
RectF(RectF r)
RectF(Rect r)- Rect
构造函数有三个,最常用的也是根据的四个点来构造矩形
Rect()
Rect(int left, int top, int right, int bottom)
Rect(Rect r)
canvas.drawRect(100, 100, 300, 300, paint);
canvas.drawRect(new Rect(400, 100, 600, 300), paint);
canvas.drawRect(new RectF(100, 400, 300, 600), paint);
效果图:

3、使用 Canvas 绘制圆角矩形
void drawRoundRect (RectF rect, float rx, float ry, Paint paint)
void drawRoundRect (float left, float top, float right, float bottom, float rx, float ry, Paint paint)
参数:
- rect:要画的矩形
- rx:生成圆角的椭圆的 X 轴半径
- ry:生成圆角的椭圆的 Y 轴半径
onDraw 中代码实现:
canvas.drawRoundRect(100, 100, 300, 300, 50, 50,paint);
canvas.drawRoundRect(new RectF(100, 400, 300, 600), 50, 50,paint);

4、使用 Canvas 绘制椭圆
椭圆是根据矩形生成的,以矩形的长为椭圆的 X 轴,矩形的宽为椭圆的 Y 轴,建立的椭圆图形
void drawOval (RectF oval, Paint paint)
参数:
- RectF oval:用来生成椭圆的矩形
onDraw 方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(100, 400, 700, 700, paint);
paint.setColor(Color.BLUE);
canvas.drawOval(new RectF(100, 400, 700, 700), paint);
}
效果图:

5、使用 Canvas 绘制圆弧
弧是椭圆的一部分,而椭圆是根据矩形来生成的,所以弧当然也是根据矩形来生成的。
void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
参数:
- RectF oval:生成圆弧的矩形
- float startAngle :圆弧开始的角度,以 X 轴正方向为 0 度
- float sweepAngle:圆弧持续的角度
- boolean useCenter:是否显示弧的两边,true,显示,false 不显示,只有一条弧线
onDraw 方法:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//0 - 90 度,不显示弧边
canvas.drawRect(100, 300, 400, 500, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(new RectF(100, 300, 400, 500), 0, 90, false, paint);
//0 - 90 度,显示弧两边
paint.setColor(Color.RED);
canvas.drawRect(100, 600, 400, 800, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(new RectF(100, 600, 400, 800), 0, 90, true, paint);
//-90 - 90 度,不显示弧两边
paint.setColor(Color.RED);
canvas.drawRect(100, 900, 400, 1100, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(new RectF(100, 900, 400, 1100), -90, 180, false, paint);
//-90 - 90 度,显示弧两边
paint.setColor(Color.RED);
canvas.drawRect(100, 1200, 400, 1400, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(new RectF(100, 1200, 400, 1400), -90, 180, true, paint);
//0 - 360 度,显示弧两边
paint.setColor(Color.RED);
canvas.drawRect(500, 700, 800, 900, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(new RectF(500, 700, 800, 900), 0, 360, true, paint);
}
效果图:

6、使用 Canvas 画直线
void drawLine (float startX, float startY, float stopX, float stopY, Paint paint)
参数:
- float startX:开始点 X 坐标
- float startY:开始点 Y 坐标
- float stopX:结束点 X 坐标
- float stopY:结束点 Y 坐标
onDraw 方法:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(100, 100, 500, 900, paint);
paint.setStrokeWidth(50);
canvas.drawLine(200, 100, 600, 900, paint);
}
效果图:

7、使用 Canvas 画多条直线
void drawLines (float[] pts, Paint paint)
void drawLines (float[] pts, int offset, int count, Paint paint)
参数:
- float[] pts:pts 是点的集合,每两个点形成一条连接线,100, 100, 500, 900 这四个数字其实就是确定了要连接的两个点的位置
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float[] pts = {100, 100, 200, 200, 300, 300, 500, 500};
canvas.drawLines(pts, paint);
}
效果图:

暂时先介绍这么多,关于 drawText 以及 drawPath ,这两个东西牵扯比较多,稍后会单独开两篇介绍。