HenCoder自定义View学习 - 自定义绘制学习笔记

前言:该系列文章为记录学习扔物线(总是叫成抛物线。大佬别怪我)自定义View系列文章的学习笔记,两个目的:一是总结自己在学习过程中遇到的疑难点;二是希望能让自己通过写博客的方式持之以恒的学下去。


感谢扔物线大佬提供了这么优质的项目供我们学习!


二话不说,我也反手就是一个扔物线大佬的自定义View项目传送门:HenCoder,给高级Android工程师的进阶手册


首先了解三个东西:

  1. Canvas
    Canvas翻译过来为画布,从字面就可以看出来它的意思就是我们所有需要绘制的东西都是在Canvas上的,这个也是自定义绘制的关键,它有两类方法:
    绘制类
    drawXXX()方法,画线、画圆、画点、画路线等等,绘制各种图形的方法应有尽有,需要配合Paint(下面介绍)使用。
    辅助类
    范围的裁切:举个例子:
    裁切
    这是我使用CSDN点击修改头像时的截图,底部是我选择的完整图片,白色虚线就是裁切的范围,点击提交后只会保存这个范围内的部分。相当于拿一把剪刀将不需要的部分剪掉。当然,裁切的大小、样式(正方形、圆形、五角星)都可以通过canvas完成。
    几何变换:在生活中的绘画,画完后的画布我们可以将其任意翻折、旋转,在canvas中我们能做的远比我们想象的多。
  2. Paint
    我又要实力翻译一波:画笔,有了画布,还需要一只笔来进行作画,paint就是这个作用,它可以控制我们将要绘制的颜色、粗细、实心空心等等,能做的也非常多,后面慢慢记录。
  3. onDraw()方法
    前面的canvas和paint需要在View的onDraw()方法中使用,我们可以在这个方法中控制先画哪个再画哪个,把我们要画的东西覆盖在View上方还是作为View的背景?这就是onDraw()。

预备知识:坐标系
首先讲一下坐标系(这里的坐标系是相对于自定义View的),每一个View都有自己的坐标系,原点是View自身的左上角,x轴和我们中学学的一样,水平方向左负右正,y轴的正负方向与中学的数学坐标系不一样,竖直方向,上负下正:
坐标系


Canvas的绘制方法

  • drawColor(@ColorInt int color)
    把整个画布填充上指定颜色。
// 绘制黑色
canvas.drawColor(Color.BLACK);

绘制黑色

// 绘制蓝色
canvas.drawColor(Color.BLUE);

绘制蓝色

  • drawCircle(float centerX, float centerY, float radius, Paint paint):绘制圆形
    centerX、centerY为圆的圆心所在的坐标,radius为圆的半径
canvas.drawCircle(300,300,250,paint)

绘制圆形

另外在Hencoder中这里把Paint的某些设置也提及了,我就把Paint先放一放,后面的笔记再回顾并且集中记录。

  • drawRect(float left, float top, float right, float bottom, Paint paint):绘制矩形
    left, top, right, bottom 是矩形四条边的坐标。
canvas.drawRect(100, 100, 500, 500, paint);

绘制矩形

  • drawPoint(float x, float y, Paint paint):绘制点
    x、y同样是点的坐标,但是点的大小和形状就要通过paint来实现了。点的大小通过paint.setStrokeWidth(width)设置,点的形状通过paint.setStrokeCap(cap) 设置:Paint.Cap.ROUND是圆点,Paint.Cap.SQUARE或者Paint.Cap.BUTT是方形的点。
paint.setStrokeWidth(50); // 50px大小的点
paint.setStrokeCap(Paint.Cap.ROUND); // 圆形
canvas.drawPoint(100, 100, paint); // 绘制在(100,100)坐标上

paint.setStrokeWidth(100); // 100px大小的点
paint.setStrokeCap(Paint.Cap.SQUARE); // 方形
canvas.drawPoint(300, 100, paint); // 绘制在(300,100)坐标上

绘制点
这里的绘制圆点、方点,既可以通过drawPoint实现,也可以通过drawCircle和drawRect实现。

  • drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint):批量绘制点
    这个方法可以绘制多个点。pts是点的坐标数组,每两个确定一个点;offset是跳过数组中的前几个数再开始绘制;count表示一共绘制多少个,就是在数组中取count*2个值。
float[] points = {0, 0, 50, 50, 50, 100, 100, 50, 100, 100, 150, 50, 150, 100};  
/* 跳过两个数,即前两个 0 */
/* 一共绘制 8 个数(4 个点):(50, 50) (50, 100) (100, 50) (100, 100),后面的150, 50, 150, 100都不要了*/
canvas.drawPoints(points, 2 , 8 , paint);

批量绘制点

  • drawOval(float left, float top, float right, float bottom, Paint paint):绘制椭圆
    绘制横着的或者竖直的椭圆,斜的需要配合canvas的几何变换实现。left、top、right、bottom 是这个椭圆的左、上、右、下四个边界点的坐标,参考drawRect。
// 横着的椭圆
canvas.drawOval(100, 250, 600, 450, paint);
// 竖直的椭圆
canvas.drawOval(700, 100, 900, 600, paint);

绘制椭圆

绘制椭圆还有一个重载的方法:drawOval(RectF rect, Paint paint),其中RectF是一个实现了Parcelable接口的类,它只有四个属性left、top、right、bottom,所以单从cavans的绘制来说用法也很简单,但是它内部还有很多方法,比如:width()、height()、centerX()、centerY()等等,从方法名就可以很容易的看出来所代表的意义。

我们也可以通过绘制椭圆来达到绘制圆形drawCircle的效果,只要将四个参数的距离计算好即可。

// 利用绘制椭圆绘制圆形,达到与drawCircle同样的效果
canvas.drawOval(100, 200, 300, 400, paint);
  • drawLine(float startX, float startY, float stopX, float stopY, Paint paint):绘制线
    startX, startY, stopX, stopY 分别是线的起点和终点坐标,这个很简单。
paint.setStrokeWidth(10);//设置线的宽度为10px
canvas.drawLine(100, 100, 800, 800, paint);

绘制线

  • drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint):批量绘制线
    与drawPoint和drawPoints同理。

  • drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint):绘制圆角矩形
    left, top, right, bottom 是四条边的坐标,rx 和 ry 是圆角的横向半径和纵向半径,这两个参数如何理解,用代码画出来就明了了。

canvas.drawRoundRect(100, 200, 500, 450, 100, 50, paint);

canvas.drawRoundRect(600, 200, 1000, 450, 50, 100, paint);

绘制圆角矩形

  • drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint):绘制弧形或扇形
    这个方法我们可以这么理解,首先用left、top、right、bottom绘制一个椭圆;startAngle为这个弧形的起始角度(x轴正方向为0°,顺时针+,逆时针-);sweepAngle为弧形划过的角度,也就是弧形的角度;useCenter为这个弧形是否连接圆心,false为弧形,true为扇形。
    还是用代码和图理解的比较快:
    首先我们理解startAngle和sweepAngle的含义:
// 这是一个扇形
canvas.drawArc(200, 100, 800, 500, -110, 100, true, mPaint);

理解startAngle和sweepAngle

所以上面的代码就是把上图右边蓝色区域截取出来一个扇形。

/* 注意这里的椭圆大小是一致的,区别是startAngle和sweepAngle不同,还有是否连接圆心 */
canvas.drawArc(200, 100, 800, 500, -110, 100, true, mPaint); // 绘制扇形
canvas.drawArc(200, 100, 800, 500, 20, 140, false/*这里不连接圆心*/, mPaint); // 绘制弧形

绘制弧形或扇形1

/* 注意这里的第二行代码与上图的代码只有是否连接圆心区别 */
canvas.drawArc(200, 100, 800, 500, -110, 100, true, mPaint); // 绘制扇形
canvas.drawArc(200, 100, 800, 500, 20, 140, true/*这里连接圆心*/, mPaint); // 绘制弧形

绘制弧形或扇形2


看到这里请各位原谅我的画图,真的。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值