在 Android 中,Canvas 相当于画布,而 Paint 相当于画笔;那么这两个配合使用就可以画出来我们想要的形状了。
首先我们新建一个类,名字叫 MyView,重写 onDraw() 方法,代码如下:
@SuppressLint("AppCompatCustomView")
public class MyView1 extends View {
private Paint mPaint;
public MyView1(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
1. 画点
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画一个点;drawPoint参数为:点的x坐标、点的y坐标、画笔
*/
mPaint.setColor(Color.RED);
//设置画笔宽度
mPaint.setStrokeWidth(50);
canvas.drawPoint(100,100,mPaint);
}
在代码中添加上面的代码,一个点就画出来了,下面是效果图:
当然,也可以连续的画多个点,代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 多个点,pts中参数为:
* 第一个点的x坐标、第一个点的y坐标;
* 第二个点的x坐标、第二个点的y坐标;
* 第三个点的x坐标、第三个点的y坐标;
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(50);
float[] pts = {100,100,200,200,300,300};
canvas.drawPoints(pts,mPaint);
}
效果图如下:
连续的画多个点还有一个方法,具体看下面代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 多个点,drawPoints参数为:
* 1.要绘制的点数组[x0 y0 x1 y1 x2 y2…]。
* 2.开始绘制前要跳过的值的个数。下面的offset=2:跳过前两个坐标,从第三个坐标开始画,即从第二个点开始画
* 3.跳过个数后,要处理的值的个数。下面的count=8:跳过前两个坐标,继续画8个坐标,即再画4个点
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(50);
float[] pts = {100,100,200,200,300,300,400,400,500,500,600,600};
canvas.drawPoints(pts,2,8,mPaint);
}
效果图如下:
2. 画线
确定两点位置既可以画出一条线,代码也很简单:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画一条线
* 参数为:
* 第一个参数:x开始坐标
* 第二个参数:y开始坐标
* 第三个参数:x结束坐标
* 第四个参数:y解释坐标
* 第五个参数:画笔
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
canvas.drawLine(10,10,200,200,mPaint);
}
效果图如下:
3. 画三角形
三角形即是确定三个点坐标,便可以画出一个三角形了,代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画三角形
* 一共12个坐标,参数分别为:
* 1-4:第一条线的起始x,y坐标和结束x,y坐标
* 5-8:第二条线的起始x,y坐标和结束x,y坐标
* 9-12:第三条线的起始x,y坐标和结束x,y坐标
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
float[] pts = {400,400,700,700,400,400,100,700,100,700,700,700};
canvas.drawLines(pts,mPaint);
}
效果图如下:
4. 画矩形
确定三个点坐标可以画出三角形,那么确定四个点的坐标也可以画出一个矩形;这里给出另一个画矩形的方法,确定第一个点 (左上角) 的坐标和第四个点 (右下角) 的坐标也可以滑出一个矩形,看下面的代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画矩形,单位是像素,参数为:
* 前两个:第一个点的坐标;后两个:第四个点的坐标
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
canvas.drawRect(0,0,200,400,mPaint);
}
效果图如下:
可以看出,这个是个实心的,和上面一条线一条线画出来的不怎么一样,其实改变一个参数即可,如下面代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画矩形另一种方式
* 三种风格为:
* Style.STROKE:只描边
* Style.FILL:填充
* Style.FILL_AND_STROKE:填充并描边
* Rect中四个参数:前两个:第一个点的坐标;后两个:第四个点的坐标
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
Rect rect = new Rect(100,100,300,300);
canvas.drawRect(rect, mPaint);
}
可以看出只需要设置 Style 即可了,下面是效果图:
5. 画圆角矩形
矩形画完,就看一下如何画圆角矩形,也是很简单,看代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 圆角矩形
* drawRoundRect中参数为:
* 第一个和第二个:第一个点坐标
* 第三个和第四个:第四个点坐标
* 第五个和第六个:x、y轴上的圆角大小
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRoundRect(100, 100, 200, 200, 20, 20, mPaint);
}
效果图如下:
6. 画圆形
画一个圆只需要确定中点的坐标和半径大小就可以画出来了,代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画圆形,参数为:
*前两个:中心点的坐标;第三个:半径大小
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
canvas.drawCircle(200,100,50,mPaint);
}
下面是效果图:
7. 画椭圆
椭圆是矩形的内切圆,也就是画椭圆之前要先画出矩形,然后再画出椭圆,代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画椭圆1
* 先画一个矩形,再在矩形中画椭圆
* RectF中参数为:前两个是矩形第一个点的坐标;后两个是矩形最后一个点的坐标
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
RectF rectF = new RectF(100,100,500,400);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLACK);
canvas.drawOval(rectF,mPaint);
}
效果图如下:
这里要注意的是:只需要给出矩形的第一个点坐标和第四个点坐标就可以画出椭圆了,和画矩形十分相似;
下面再来看一个例子:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画椭圆2
* 椭圆是根据一个矩形的内切圆而定的,
* 所以也可以直接给出矩形的第一个点坐标和最后一个点坐标,直接画出椭圆,
* 隐藏了矩形,直接显示了椭圆
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawOval(100, 100, 600, 300, mPaint);
}
效果图如下:
8. 画弧
弧是椭圆来定的,椭圆是根据矩形而定的,那么弧和矩形也脱不了干系:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画弧
* drawArc中参数:
* startAngle :圆弧开始的起始角(度)
* sweepAngle :顺时针测量扫掠角(度)即:90度为1/4个椭圆;180为1/2个椭圆
* useCenter :false,只显示一段弧;否则显示线段和弧
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
RectF rectF = new RectF(100,100,600,300);
canvas.drawArc(rectF,0,90,true,mPaint);
}
下面是效果图:
上面有个参数 useCenter 改为 true 是上面的效果;来看一下改为 false 的效果图:
可以看到少了两条线,对画弧有一定了解后,来看一下弧的来历:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画弧2:弧的来历
* drawArc中参数:
* startAngle :圆弧开始的起始角(度)
* sweepAngle :顺时针测量扫掠角(度)即:90度为1/4个椭圆;180为1/2个椭圆
* useCenter :false,只显示一段弧;否则显示线段和弧
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
RectF rectF = new RectF(100,100,600,300);
//先画一个矩形
canvas.drawRect(rectF,mPaint);
//再画一个椭圆
mPaint.setColor(Color.BLACK);
canvas.drawOval(rectF,mPaint);
//最后画弧
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,true,mPaint);
}
可以看出,首先画出一个矩形,其次画出一个椭圆,最后得到了一段弧,下面是效果图:
可以清楚看出来了,不懂的来看下面图片的分析,这是数学的东西,弧度什么的我就不再多说了:
看懂之后,最后再看一个关于弧度的小例子:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 画弧3
* drawArc中参数:
* startAngle :圆弧开始的起始角(度)
* sweepAngle :顺时针测量扫掠角(度)即:90度为1/4个椭圆;180为1/2个椭圆
* useCenter :false,只显示一段弧;否则显示线段和弧
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
RectF rectF = new RectF(100,100,600,300);
canvas.drawArc(rectF,90,-180,true,mPaint);
}
效果图如下:
9. 画多边形
基本的都了解完,来看一下自定义多边形:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 多边形1
* moveTo():第一个点坐标
* lineTo():第二个点坐标,第三个点坐标等;后面所有点坐标都写在里面
* close():写完点之后调用;它让此多边形保持闭合状态
*/
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
Path path = new Path();
path.moveTo(100,100);
path.lineTo(100,500);
path.lineTo(300,500);
path.lineTo(600,200);
path.close();
canvas.drawPath(path,mPaint);
}
下面是效果图:
很丑的多边形出现了;我来在多边形上又加图形,修改代码为:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 多边形2
* Direction方法:指定添加到路径时封闭形状(例如矩形、椭圆)的方向。
* Direction方法中有两个参数:
* CW:即clockwise,顺时针方向
* CCW:即counter-clockwise,逆时针方向
*/
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
Path path = new Path();
path.moveTo(100, 100);
path.lineTo(100, 500);
path.lineTo(300, 500);
path.lineTo(600, 200);
path.close();
//多边形中添加一个圆
path.addCircle(100,100,30,Path.Direction.CW);
//多边形中添加一个矩形
path.addRect(100,300,200,500,Path.Direction.CCW);
//多边形中添加一个弧
path.addArc(0,400,200,600,0,-90);
canvas.drawPath(path, mPaint);
}
效果图如下:
很奇怪的图形出现了,大家可以自己多写点作为练习,加深理解;
10. 图片中添加文字
图形画的差不多了,下面来在上面添加一些文字:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 形状内添加文字
* drawTextOnPath内的参数为:
* 1.要绘制的文本
* 2.文本应遵循的基线路径,即创建的图形
* 3.沿路径添加到文本起始位置的距离;即距离x轴的距离
* 4.文本定位路径上(-)或下(+)的距离;越大越偏离图形
* 5.画笔
*/
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
String text = "Hello, everybody!I am wuqingsen";
Path path = new Path();
path.addCircle(400, 400, 200, Path.Direction.CCW);
canvas.drawPath(path, mPaint);
mPaint.setTextSize(60);
mPaint.setColor(Color.BLACK);
//设置抗锯齿
mPaint.setAntiAlias(true);
canvas.drawTextOnPath(text, path, 0, 0, mPaint);
}
下面是效果图:
密密麻麻,丑了吧唧;上面 drawTextOnPath 方法中的第三个和第四个参数是什么意思呢,我将两个值便大后,代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 文字2
*/
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.STROKE);
String text = "Hello, everybody!I am wuqingsen";
Path path = new Path();
path.addCircle(400, 400, 200, Path.Direction.CCW);
canvas.drawPath(path, mPaint);
mPaint.setTextSize(60);
mPaint.setColor(Color.BLACK);
//设置抗锯齿
mPaint.setAntiAlias(true);
canvas.drawTextOnPath(text, path, 100, 60, mPaint);
}
效果图如下:
这样对这两个参数应该也有所了解。我将 CCW 改为 CW ;效果图如下:
可以看出方向变为了顺时针。
Android 中 Paint 和 Canvas 的简单使用就到这里了。
有兴趣的可以点这里:涂鸦功能的简单实现