自定义view1-1绘制基础

canvas的起始点是左上角
* Canvas
Canvas类里所有的draw打头的方法
* Paint

Paint.setStyle(Style style) //设置绘制模式
Paint.setColor(int color) //设置颜色
Paint.setStrokeWidth(float width) //设置线条宽度
Paint.setTextSize(float textSize) //设置文字大小
Paint.setAntiAlias(boolean aa) //设置抗锯齿开关

Canvas.drawColor(@ColorInt int color) 颜色填充

在整个绘制区域统一涂上指定的颜色,覆盖掉原有内容.
drawColor(Color.BLACK);使用系统颜色
drawColor(Color.parse("#88880000");手动设置颜色
也可以通过drawRGB(int r, int g, int b) 和 drawARGB(int a, int r, int g, int b)设置颜色

drawCircle(float centerX, float centerY, float radius, Paint paint) 画圆

1.前两个参数 centerX CenterY 是圆心的坐标
2.radius:是圆的半径,单位是像素
3.paint:提供颜色、线条粗心、阴影等
* Paint.setStyle(Paint.Style style)
style 有三种 默认模式是FILL
1. FILL:填充模式
2. STROKE:画线模式(勾边模式)
3. FILL_AND_STROKE 即画线又填充
* Paint.setStrokeWidth(float width)
设置画线的宽度
* 抗锯齿
可以在new Paint()时添加ANTI_ALIAS_FLAG;

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

也可以通过Paint.setAntiAlias(boolean aa) 来动态设置抗锯齿

drawRect(float left, float top, float right, float bottom, Paint paint) 画矩形

left, top, right, bottom 是矩形四条边的坐标。
拥有两个重载方法
drawRect(RectF rect, Paint paint) 和 drawRect(Rect rect, Paint paint)

drawPoint(float x, float y, Paint paint) 画点

点的大小可以通过 paint.setStrokeWidth(width) 来设置

点的形状可以通过 paint.setStrokeCap(cap) 来设置
ROUND 画出来是圆形的点
SQUARE 或 BUTT 画出来是方形的点

drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint) 画点(批量)

pts:这个数组是点的坐标,每两个成一对
offset 表示跳过数组的前几个数再开始记坐标
count 表示一共要绘制几个点(坐标是两个一组,这里指的是总数量不是组)
eg:

float[] points = {0, 0, 50, 50, 50, 100, 100, 50, 100, 100, 150, 50, 150, 100};  
// 绘制四个点:(50, 50) (50, 100) (100, 50) (100, 100)
canvas.drawPoints(points, 2 /* 跳过两个数,即前两个 0 */, 8 /* 一共绘制 8 个数(4 个点)*/, paint);

drawOval(float left, float top, float right, float bottom, Paint paint) 画椭圆

只能绘制横着的或者竖着的椭圆,不能绘制斜的
重载方法
drawOval(RectF rect, Paint paint),让你可以直接填写 RectF 来绘制椭圆。

drawLine(float startX, float startY, float stopX, float stopY, Paint paint) 画线

drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint) 画线(批量)

可以实现汉字

drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) 画圆角矩形

重载方法
drawRoundRect(RectF rect, float rx, float ry, Paint paint)

drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 绘制弧形或扇形

  • stratAngle:是弧形的起始角度
  • sweepAngle:是弧形划过的角度
  • useCenter:表示是否连接到圆心
paint.setStyle(Paint.Style.FILL); // 填充模式  
canvas.drawArc(200, 100, 800, 500, -110, 100, true, paint); // 绘制扇形  
canvas.drawArc(200, 100, 800, 500, 20, 140, false, paint); // 绘制弧形  
paint.setStyle(Paint.Style.STROKE); // 画线模式  
canvas.drawArc(200, 100, 800, 500, 180, 60, false, paint); // 绘制不封口的弧形  

drawPath(Path path, Paint paint) 画自定义图形

eg:

public class PathView extends View {

    Paint paint = new Paint();
    Path path = new Path(); // 初始化 Path 对象

    ......

    {
      // 使用 path 对图形进行描述(这段描述代码不必看懂)
      path.addArc(200, 200, 400, 400, -225, 225);
      path.arcTo(400, 200, 600, 400, -180, 225, false);
      path.lineTo(400, 542);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);

      canvas.drawPath(path, paint); // 绘制出 path 描述的图形(心形),大功告成
    }
}

Path
可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。
有两类方法
一类是直接描述路径
另一类是辅助的设置或计算

Path 方法第一类:直接描述路径。

这一类方法还可以细分为两组:添加子图形和画线(直线或曲线)
1.第一组addXxx() ——添加子图形
addCircle(float x, float y, float radius, Direction dir) 添加圆
dir:画圆的路径方向
路径方向
1. 顺时针 (CW clockwise)
2. 逆时针 (CCW counter-clockwise)
只影响填充时范围

2.第二组 xxxTo() ——画线(直线或曲线)
ineTo(float x, float y) / rLineTo(float x, float y) 画直线
从当前位置向目标位置画一条直线
lineTo(x, y) 的参数是绝对坐标,而 rLineTo(x, y) 的参数是相对当前位置的相对坐标
当前位置:所谓当前位置,即最后一次调用画 Path 的方法的终点位置。初始值为原点 (0, 0)。
eg:

paint.setStyle(Style.STROKE);  
path.lineTo(100, 100); // 由当前位置 (0, 0) 向 (100, 100) 画一条直线
path.rLineTo(100, 0); // 由当前位置 (100, 100) 向正右方 100 像素的位置画一条直线

quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 画三次贝塞尔曲线
moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
eg:

paint.setStyle(Style.STROKE);
path.lineTo(100, 100); // 画斜线
path.moveTo(200, 100); // 我移
path.lineTo(200, 0); // 画竖线

arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 画弧形
forceMoveTo 参数的意思是,绘制是要「抬一下笔移动过去」,还是「直接拖着笔过去」

paint.setStyle(Style.STROKE);
path.lineTo(100, 100);
path.arcTo(100, 100, 300, 300, -90, 90, true); // 强制移动到弧形起点(无痕迹)

paint.setStyle(Style.STROKE);  
path.lineTo(100, 100);  
path.arcTo(100, 100, 300, 300, -90, 90, false); // 直接连线连到弧形起点(有痕迹)  

addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)
addArc() 只是一个直接使用了 forceMoveTo = true 的简化版 arcTo() 。

paint.setStyle(Style.STROKE);  
path.lineTo(100, 100);  
path.addArc(100, 100, 300, 300, -90, 90);  

close() 封闭当前子图形
把当前的子图形封闭,即由当前位置向当前子图形的起点绘制一条直线

paint.setStyle(Style.STROKE);  
path.moveTo(100, 100);  
path.lineTo(200, 100);  
path.lineTo(150, 150);  

paint.setStyle(Style.STROKE);  
path.moveTo(100, 100);  
path.lineTo(200, 100);  
path.lineTo(150, 150);  
path.close(); // 使用 close() 封闭子图形。等价于 path.lineTo(100, 100)  

close() 和 lineTo(起点坐标) 是完全等价的。
当需要填充图形时(即 Paint.Style 为 FILL 或 FILL_AND_STROKE),Path 会自动封闭子图形。

Path 方法第二类:辅助的设置或计算
Path.setFillType(Path.FillType ft) 设置填充方式
四个填充方式
* EVEN_ODD
* WINDING (默认值)
* INVERSE_EVEN_ODD
* INVERSE_WINDING
其中后面的两个带有 INVERSE前缀的,只是前两个的反色版本,所以只要把前两个,即 EVEN_ODD 和 WINDING,搞明白就可以了。
WINDING 是「全填充」,而 EVEN_ODD 是「交叉填充」
EVEN_ODD
even-odd rule (奇偶原则):对于平面中的任意一点,向任意方向射出一条射线,这条射线和图形相交的次数(相交才算,相切不算哦)如果是奇数,则这个点被认为在图形内部,是要被涂色的区域;如果是偶数,则这个点被认为在图形外部,是不被涂色的区域。
WINDING
即 non-zero winding rule (非零环绕数原则)
以 0 为初始值,对于射线和图形的所有交点,遇到每个顺时针的交点(图形从射线的左边向右穿过)把结果加 1,遇到每个逆时针的交点(图形从射线的右边向左穿过)把结果减 1,最终把所有的交点都算上,得到的结果如果不是 0,则认为这个点在图形内部,是要被涂色的区域;如果是 0,则认为这个点在图形外部,是不被涂色的区域。

而 INVERSE_EVEN_ODD 和 INVERSE_WINDING ,只是把这两种效果进行反转

drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 画 Bitmap

绘制 Bitmap 对象,也就是把这个 Bitmap 中的像素内容贴过来。其中 left 和 top 是要把 bitmap 绘制到的位置坐标。
重载方法

drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) /
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) /
drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

rawBitmap 还有一个兄弟方法 drawBitmapMesh(),可以绘制具有网格拉伸效果的 Bitmap。
drawBitmapMesh() 的使用场景较少,所以不讲了,如果有兴趣你可以自己研究一下。

drawText(String text, float x, float y, Paint paint) 绘制文字

canvas.drawText(text, 200, 100, paint);  

Paint.setTextSize(float textSize)
设置文字的大小

发表评论

电子邮件地址不会被公开。 必填项已用*标注