自定义View之Canvas(画布)的详解

接下来学习一下自定义View之Canvas(画布)的详解

先来看看Canvas常用方法:

功能分类Canvas常用方法备注
绘制颜色drawARGB通过设置ARGB值绘制颜色
drawRGB通过设置RGB值绘制颜色
drawColor绘制颜色
绘制图形drawPoint,drawPoints绘制点,点集合
drawLine,drawLines绘制线,线集合
drawRect绘制矩形
drawCircle绘制圆
drawOval绘制椭圆
drawArc绘制弧
画布操作translate、rotate、scale、save、restore依次为位移、旋转、缩放、保存画布和恢复画布
drawPath按路径绘制

Canvas绘制颜色的API:

canvas.drawARGB(int a, int r, int g, int b)
canvas.drawRGB(int r, int g, int b)
canvas.drawColor(int color) 
canvas.drawColor(int color, PorterDuff.Mode mode)

颜色的四种模式:

颜色模式备注
ARGB8888四通道高精度(32位)
ARGB4444四通道低精度(16位)
RGB565屏幕默认模式(16位)
Alpha8仅有透明通道(8位)

ARGB分别代表的类型:

类型备注
A(Alpha)透明度,取值范围 [0,255],0代表完全透明,255代表完全不透明
R(Red)红色,取值范围 [0,255],0代表无色,255代表红色
G(Green)绿色,取值范围 [0,255],0代表无色,255代表绿色
B(Blue)蓝色,取值范围 [0,255],0代表无色,255代表蓝色

从表中可以看出,ARGB的取值范围都是[0,255],其实就是16进制中的[0x00,0xff]
A从0x00到0xff对应表示从透明到不透明
RGB从0x00到0xff对应表示颜色从浅到深

示例代码:

canvas.drawARGB(0, 0, 0, 0);
canvas.drawARGB(255, 255, 0, 0);
canvas.drawARGB(255, 0, 255, 0);
canvas.drawARGB(255, 0, 0, 255);

结果:
这里写图片描述




Canvas绘制形状

canvas.drawPoint(float x, float y, Paint paint) //绘制点
canvas.drawPoints( float[] pts, Paint paint) //绘制多个点

canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint) //绘制线
canvas.drawLines(float[] pts, Paint paint)//绘制多条线

canvas.drawRect(float left, float top, float right, float bottom, Paint paint) //绘制矩形
canvas.drawRect(RectF rect, Paint paint) //绘制矩形

canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,Paint paint) //绘制圆角矩形
canvas.drawRoundRect(RectF rect, float rx, float ry, Paint paint) //绘制圆角矩形

canvas.drawCircle(float cx, float cy, float radius,Paint paint) 绘制圆

canvas.drawOval(float left, float top, float right, float bottom,Paint paint) //绘制椭圆
canvas.drawOval(RectF oval,Paint paint) //绘制椭圆

canvas.drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter,Paint paint) //绘制圆弧
canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) //绘制圆弧


画点

        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(20f);
        canvas.drawPoint(300, 300, paint);
        float[] pts = {400, 400, 500, 400, 600, 400};
        canvas.drawPoints(pts, paint);

drawPoint的两个参数就是(x,y)。而drawPoints的第一个参数是float数组,每两个就代表一个坐标,如上面的例子有(400,400)、(500,400)和(600,400)。结果:
这里写图片描述


画线

        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(20f);
        canvas.drawLine(200, 500, 1000, 500, paint);
        float[] pts = {800, 400, 1000, 500,
                800, 600, 1000, 500};
        canvas.drawLines(pts, paint);

drawLine的前四个参数就代表起始坐标(x1,y1),和终点坐标(x2,y2)。而drawLines第一个参数也是float数组,如上面的例子前四个起始点(800, 400),终点(1000, 500)。接着下一条线的起点(800, 600),终点(1000, 500)。结果:
这里写图片描述


画矩形

        Paint paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.STROKE); //只描边
        paint.setStrokeWidth(10f);
        //1.直接通过坐标画矩形
        canvas.drawRect(100, 100, 800, 500, paint);
        //2.通过Rect 画矩形
        Rect mRect = new Rect(100, 550, 800, 950);
        paint.setStyle(Paint.Style.FILL); //只描内容
        canvas.drawRect(mRect, paint);
        //3.通过RectF 画矩形
        RectF mRectF = new RectF(100, 1000, 800, 1400);
        paint.setStyle(Paint.Style.FILL_AND_STROKE); //描边和内容
        paint.setStrokeWidth(10f);
        canvas.drawRect(mRectF, paint);

以上的坐标参数都是四个的,即用前面两个代表左上角坐标(x1,y1)和右下角坐标(x2,y2)来确定矩形的。结果:
这里写图片描述


画圆

        Paint paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.STROKE); //只描边
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        canvas.drawCircle(600, 600, 200, paint);

drawCircle方法前两个是圆点的坐标(x1,y1),而第三个参数是圆的半径值。结果:
这里写图片描述


画椭圆

        Paint paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.STROKE); //只描边
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        //第一种,通过left top right bottom来确定矩形,然后画矩形的内切椭圆
        canvas.drawOval(300, 100, 900, 500, paint);


        //第二种,通过RectF 画椭圆,和第一种原理是一样的
        RectF mRectF = new RectF(100, 600, 1000, 900);
        paint.setStyle(Paint.Style.FILL_AND_STROKE); //描边和内容
        canvas.drawOval(mRectF, paint);

结果:
这里写图片描述


画圆角矩形

        Paint paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.STROKE); //只描边
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        //第一种
        canvas.drawRoundRect(200, 100, 1000, 500, 20f, 20f, paint);

        //第二种通过RectF 来画圆角矩形
        paint.setStyle(Paint.Style.FILL_AND_STROKE); //描边和内容
        RectF mRect = new RectF(200, 600, 1000, 1000);
        canvas.drawRoundRect(mRect, 20f, 20f, paint);

RectF构造函数中,前两个参数就是左上角的坐标,后两个就是右下角的坐标。rx和ry就是圆角的半径。结果:
这里写图片描述


画圆弧

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)
drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, Paint paint)

第二个方法里面的个别参数,形成实例也可以使用第一个方法的。所以直接看第二个方法:

drawArc备注
left左上角坐标的X轴坐标
top左上角坐标的Y轴坐标
right右下角坐标X轴坐标
bottom右下角坐标Y轴坐标
startAngle起始角度
sweepAngle扫过的角度
useCenter是否使用中心
paint画笔

演示一下:

        Paint paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.FILL); //只内容
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        //通过下面前两个圆弧对比很明显,useCenter为true,最后图形是一个扇形,
        canvas.drawArc(100, 100, 500, 500, 0, 90, true, paint);

        //useCenter为false,则最后图形是起始点和结束点之间的连线和圆弧围成的面积。
        canvas.drawArc(100, 500, 500, 900, 0, 90, false, paint);

        //通过RectF 设置的区域范围画弧
        RectF mRectF = new RectF(100, 900, 500, 1300);
        paint.setStyle(Paint.Style.STROKE); //只描边
        canvas.drawArc(mRectF, 0, 90, true, paint);

结果:
这里写图片描述


Canvas画布的操作

canvas.translate(float dx, float dy) //平移
canvas.rotate(float degrees) //旋转
canvas.rotate(float degrees, float px, float py) //改变旋转中心并旋转
canvas.scale(float sx, float sy) //缩放
canvas.scale(float sx, float sy, float px, float py) //改变缩放中心并缩放
canvas.save(); //保存画布
canvas.restore(); //恢复画布

Canvas画布的操作可以让我们更加容易绘制图形,Canvas画布操作只会对后面的绘制起作用,对前面已经绘制的是不影响的。

translate

translate是对坐标系的平移,且是可以多次重叠的,默认是在屏幕的左上角(0,0)。

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL); //只内容
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        //将坐标系移到Canvas宽度的一半,高度400的位置
        canvas.translate(getMeasuredWidth() / 2, 400);
        //绘制一个红色圆
        paint.setColor(Color.RED);
        canvas.drawCircle(0, 0, 100, paint);


        //坐标系原点在前面位置的基础上再往下移动250像素
        canvas.translate(0, 250);
        paint.setColor(Color.GREEN);
        canvas.drawCircle(0, 0, 100, paint);


        //坐标系原点在前面位置的基础上再往下移动250像素
        canvas.translate(0, 250);
        paint.setColor(Color.BLUE);
        canvas.drawCircle(0, 0, 100, paint);

结果:
这里写图片描述


rotate

rotate是对坐标系的旋转,rotate有两个方法

canvas.rotate(float degrees) 
canvas.rotate(float degrees, float px, float py) 

rotate第一个参数是旋转的角度,后面两个参数是可以确定旋转中心,如果不填默认是(0,0)。

演示一下:

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL); //只内容
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        //将坐标系移动到屏幕中心
        canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
        RectF rectF = new RectF(-300, -300, 0, 0);
        //绘制一个红色矩形
        paint.setColor(Color.RED);
        canvas.drawRect(rectF, paint);

        //将坐标系旋转180度,不会影响前面已经绘制的图形
        canvas.rotate(180);
        paint.setStyle(Paint.Style.FILL);
        //绘制一个蓝色矩形
        paint.setColor(Color.BLUE);
        canvas.drawRect(rectF, paint);

结果:
这里写图片描述


scale

scale也有两个方法

canvas.scale(float sx, float sy)
canvas.scale(float sx, float sy, float px, float py)

scale是缩放,缩放中心默认是坐标原点,且多次缩放是可以重叠的。scale的前两个参数sx和sy是X轴和Y轴的缩放倍数,后两个参数px和py是控制缩放中心的位置。演示一下:

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL); //只内容
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动
        //将坐标系移动到屏幕中心
        canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
        RectF rectF = new RectF(-300, -300, 0, 0);

        paint.setColor(Color.RED);
        //左上角绘制红色矩形
        canvas.drawRect(rectF, paint);
        //XY轴分别缩放到原来的1/2并以原点(0,0)位对称点进行翻转
        canvas.scale(-0.5f, -0.5f);

        //绘制绿色矩形
        paint.setColor(Color.GREEN);
        canvas.drawRect(rectF, paint);

结果:
这里写图片描述

这里的sx和sy参数取值挺有考究的,可以自己写个 demo 试试

sx sy取值范围备注
(1,+∞)根据缩放中心放大到原来的n倍
1跟原来大小一样,没变化
(0,1)根据缩放中心缩放
0sx sy有一个取0图形就消失了
(-1,0)根据缩放中心缩放并翻转
-1翻转
(-∞,-1)根据缩放中心放大并翻转


save和restore

save:表示保存Canvas之前的状态。save保存之后,可以调用Canvas的平移、缩放、旋转、错切和裁剪等操作。
restore:恢复Canvas之前保存的状态,防止save后对Canvas执行的操作对后续的绘制有影响。

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL); //只内容
        paint.setStrokeWidth(10f);
        paint.setAntiAlias(true); //设置抗锯齿
        paint.setDither(true); //设置防抖动

        //保存画布
        canvas.save();
        //坐标原点移到屏幕中心
        canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
        //以屏幕中心为坐标原点在(100,100)为圆心处绘制红色圆
        paint.setColor(Color.RED);
        RectF rectF = new RectF(0, 0, 200, 200);
        canvas.drawRect(rectF, paint);


        //恢复画布
        canvas.restore();
        //恢复画布后,坐标原点(0,0)默认在屏幕左上角,
        //即以屏幕左上角为坐标原点在(100,100)为圆心处绘制蓝色圆
        paint.setColor(Color.BLUE);
        RectF rectf = new RectF(50, 50, 100, 100);
        canvas.drawRect(rectf, paint);

结果:
这里写图片描述
以上的代码去掉save()和restore()方法,再运行,结果:
这里写图片描述

如果去掉save()和restore(),那么所有的图像都在坐标原点移动到屏幕中心后绘制;如果有save()和restore(),在restore()之后,图像的坐标原点又回到了屏幕的左上角了。

drawPath

drawPath按路径绘制,有一个方法

canvas.drawPath(Path path, Paint paint)

Path的内容有点多,就另起一篇了。




个人公众号 「Android 零零柒」,主推 Android 技术文章



参考资料:https://www.jianshu.com/p/adbe33e887be

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android自定义View中的Canvas是一个绘图容器,可以在其上进行2D绘图操作。通过Canvas,我们可以绘制图形、文字、位图等。 要在自定义View中使用Canvas,需要重写View的onDraw()方法,并在该方法中获取Canvas实例,然后进行绘制操作。 下面是一个简单的示例代码,展示如何在自定义View中使用Canvas绘制一个矩形: ```java public class MyCustomView extends View { public MyCustomView(Context context) { super(context); } public MyCustomView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawRect(100, 100, 300, 300, paint); } } ``` 在这个示例中,我们创建了一个名为MyCustomView自定义View,并重写了它的onDraw()方法。在该方法中,我们首先创建了一个Paint对象,设置了画笔的颜色为红色,并指定绘制的样式为填充。然后,使用CanvasdrawRect()方法绘制一个矩形,坐标为(100, 100)到(300, 300)。 当我们在布局文件中使用这个自定义View时,它会自动调用onDraw()方法进行绘制,从而在屏幕上显示出红色矩形。 需要注意的是,Canvas提供了许多其他绘制方法,如drawCircle()、drawText()等,可以根据需求选择合适的方法进行绘制操作。此外,还可以通过设置Paint对象的属性来实现不同的绘制效果,如线条宽度、字体大小等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值