Canvas之绘制基本形状
在上一篇自定义View分类与流程中我们了解自定义View相关的基本知识,不过,这些东西依旧还是理论,并不能拿来(zhuang)用(B), 这一次我们就了解一些能(zhaung)用(B)的东西。
在本篇文章中,我们先了解Canvas的基本用法,最后用一个小示例来结束本次教程。
一.Canvas简介
Canvas我们可以称之为画布,能够在上面绘制各种东西,是安卓平台2D图形绘制的基础,非常强大。
一般来说,比较基础的东西有两大特点:
1.可操作性强:由于这些是构成上层的基础,所以可操作性必然十分强大。
2.比较难用:各种方法太过基础,想要完美的将这些操作组合起来有一定难度。
不过不必担心,本系列文章不仅会介绍到Canvas的操作方法,还会简单介绍一些设计思路和技巧。
二.Canvas的常用操作速查表
操作类型 |
相关API |
备注 |
绘制颜色 |
drawColor, drawRGB, drawARGB |
使用单一颜色填充整个画布 |
绘制基本形状 |
drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc |
依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
绘制图片 |
drawBitmap, drawPicture |
绘制位图和图片 |
绘制文本 |
drawText, drawPosText, drawTextOnPath |
依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
绘制路径 |
drawPath |
绘制路径,绘制贝塞尔曲线时也需要用到该函数 |
顶点操作 |
drawVertices, drawBitmapMesh |
通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用 |
画布剪裁 |
clipPath, clipRect |
设置画布的显示区域 |
画布快照 |
save, restore, saveLayerXxx, restoreToCount, getSaveCount |
依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 |
画布变换 |
translate, scale, rotate, skew |
依次为 位移、缩放、 旋转、错切 |
Matrix(矩阵) |
getMatrix, setMatrix, concat |
实际画布的位移,缩放等操作的都是图像矩阵Matrix,只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 |
PS: Canvas常用方法在上面表格中已经全部列出了,当然还存在一些其他的方法未列出,具体可以参考官方文档 Canvas
三.Canvas详解
本篇内容主要讲解如何利用Canvas绘制基本图形。
绘制颜色:
绘制颜色是填充整个画布,常用于绘制底色。

关于颜色的更多资料请参考基础篇颜色
创建画笔:
要想绘制内容,首先需要先创建一个画笔,如下:
private Paint mPaint = new Paint();
private void initPaint() {
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(10f);
}
public SloopView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
在创建完画笔之后,就可以在Canvas中绘制各种内容了。
绘制点:
可以绘制一个点,也可以绘制一组点,如下:
canvas.drawPoint(200, 200, mPaint);
canvas.drawPoints(new float[]{
500,500,
500,600,
500,700
},mPaint);
关于坐标原点默认在左上角,水平向右为x轴增大方向,竖直向下为y轴增大方向。
更多参考这里 基础篇坐标系

绘制直线:
绘制直线需要两个点,初始点和结束点,同样绘制直线也可以绘制一条或者绘制一组:
canvas.drawLine(300,300,500,600,mPaint);
canvas.drawLines(new float[]{
100,200,200,200,
100,300,200,300
},mPaint);

绘制矩形:
确定一个矩形最少需要四个数据,就是对角线的两个点的坐标值,这里一般采用左上角和右下角的两个点的坐标。
关于绘制矩形,Canvas提供了三种重载方法,第一种就是提供四个数值(矩形左上角和右下角两个点的坐标)来确定一个矩形进行绘制。
其余两种是先将矩形封装为Rect或RectF(实际上仍然是用两个坐标点来确定的矩形),然后传递给Canvas绘制,如下:
canvas.drawRect(100,100,800,400,mPaint);
Rect rect = new Rect(100,100,800,400);
canvas.drawRect(rect,mPaint);
RectF rectF = new RectF(100,100,800,400);
canvas.drawRect(rectF,mPaint);
以上三种方法所绘制出来的结果是完全一样的。

看到这里,相信很多观众会产生一个疑问,为什么会有Rect和RectF两种?两者有什么区别吗?
答案当然是存在区别的,两者最大的区别就是精度不同,Rect是int(整形)的,而RectF是float(单精度浮点型)的。除了精度不同,两种提供的方法也稍微存在差别,在这里我们暂时无需关注,想了解更多参见官方文档 Rect 和 RectF
绘制圆角矩形:
绘制圆角矩形也提供了两种重载方式,如下:
RectF rectF = new RectF(100,100,800,400);
canvas.drawRoundRect(rectF,30,30,mPaint);
canvas.drawRoundRect(100,100,800,400,30,30,mPaint);
上面两种方法绘制效果也是一样的,但鉴于第二种方法在API21的时候才添加上,所以我们一般使用的都是第一种。

下面简单解析一下圆角矩形的几个必要的参数的意思。
很明显可以看出,第二种方法前四个参数和第一种方法的RectF作用是一样的,都是为了确定一个矩形,最后一个参数Paint是画笔,无需多说,与矩形相比,圆角矩形多出来了两个参数rx 和 ry,这两个参数是干什么的呢?
稍微分析一下,既然是圆角矩形,他的角肯定是圆弧(圆形的一部分),我们一般用什么确定一个圆形呢?
答案是圆心 和 半径,其中圆心用于确定位置,而半径用于确定大小。
由于矩形位置已经确定,所以其边角位置也是确定的,那么确定位置的参数就可以省略,只需要用半径就能描述一个圆弧了。
但是,半径只需要一个参数,但这里怎么会有两个呢?
好吧,让你发现了,这里圆角矩形的角实际上不是一个正圆的圆弧,而是椭圆的圆弧,这里的两个参数实际上是椭圆的两个半径,他们看起来个如下图:

红线标注的 rx 与 ry 就是两个半径,也就是相比绘制矩形多出来的那两个参数。
我们了解到原理后,就可以为所欲为了,通过计算可知我们上次绘制的矩形宽度为700,高度为300,当你让 rx大于350(宽度的一半), ry大于150(高度的一半) 时奇迹就出现了, 你会发现圆角矩形变成了一个椭圆, 他们画出来是这样的 ( 为了方便确认我更改了画笔颜色, 同时绘制出了矩形和圆角矩形 ):
RectF rectF = new RectF(100,100,800,400);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawRoundRect(rectF,700,400,mPaint);

其中灰色部分是我们所选定的矩形,而里面的圆角矩形则变成了一个椭圆,实际上在rx为宽度的一半,ry为高度的一半时,刚好是一个椭圆,通过上面我们分析的原理推算一下就能得到,而当rx大于宽度的一半,ry大于高度的一半时,实际上是无法计算出圆弧的,所以drawRoundRect对大于该数值的参数进行了限制(修正),凡是大于一半的参数均按照一半来处理。
绘制椭圆:
相对于绘制圆角矩形,绘制椭圆就简单的多了,因为他只需要一个矩形矩形作为参数:
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);
canvas.drawOval(100,100,800,400,mPaint);
同样,以上两种方法效果完全一样,但一般使用第一种。

绘制椭圆实际上就是绘制一个矩形的内切图形,原理如下,就不多说了:

PS: 如果你传递进来的是一个长宽相等的矩形(即正方形),那么绘制出来的实际上就是一个圆。
绘制圆:
绘制圆形也比较简单, 如下:
绘制圆形有四个参数,前两个是圆心坐标,第三个是半径,最后一个是画笔。

绘制圆弧:
绘制圆弧就比较神奇一点了,为了理解这个比较神奇的东西,我们先看一下它需要的几个参数:
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {}
从上面可以看出,相比于绘制椭圆,绘制圆弧还多了三个参数:
startAngle
sweepAngle
useCenter
通过字面意思我们基本能猜测出来前两个参数(startAngle, sweepAngel)的作用,就是确定角度的起始位置和扫过角度, 不过第三个参数是干嘛的?试一下就知道了,上代码:
```
RectF rectF = new RectF(100,100,800,400);
// 绘制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,false,mPaint);
RectF rectF2 = new RectF(100,600,800,900);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF2,mPaint);
mPaint.setColor(Color.BLUE);
Canvas之绘制基本形状
在上一篇自定义View分类与流程中我们了解自定义View相关的基本知识,不过,这些东西依旧还是理论,并不能拿来(zhuang)用(B), 这一次我们就了解一些能(zhaung)用(B)的东西。
在本篇文章中,我们先了解Canvas的基本用法,最后用一个小示例来结束本次教程。
一.Canvas简介
Canvas我们可以称之为画布,能够在上面绘制各种东西,是安卓平台2D图形绘制的基础,非常强大。
一般来说,比较基础的东西有两大特点:
1.可操作性强:由于这些是构成上层的基础,所以可操作性必然十分强大。
2.比较难用:各种方法太过基础,想要完美的将这些操作组合起来有一定难度。
不过不必担心,本系列文章不仅会介绍到Canvas的操作方法,还会简单介绍一些设计思路和技巧。
二.Canvas的常用操作速查表
操作类型 |
相关API |
备注 |
绘制颜色 |
drawColor, drawRGB, drawARGB |
使用单一颜色填充整个画布 |
绘制基本形状 |
drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc |
依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
绘制图片 |
drawBitmap, drawPicture |
绘制位图和图片 |
绘制文本 |
drawText, drawPosText, drawTextOnPath |
依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
绘制路径 |
drawPath |
绘制路径,绘制贝塞尔曲线时也需要用到该函数 |
顶点操作 |
drawVertices, drawBitmapMesh |
通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用 |
画布剪裁 |
clipPath, clipRect |
设置画布的显示区域 |
画布快照 |
save, restore, saveLayerXxx, restoreToCount, getSaveCount |
依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 |
画布变换 |
translate, scale, rotate, skew |
依次为 位移、缩放、 旋转、错切 |
Matrix(矩阵) |
getMatrix, setMatrix, concat |
实际画布的位移,缩放等操作的都是图像矩阵Matrix,只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 |
PS: Canvas常用方法在上面表格中已经全部列出了,当然还存在一些其他的方法未列出,具体可以参考官方文档 Canvas
三.Canvas详解
本篇内容主要讲解如何利用Canvas绘制基本图形。
绘制颜色:
绘制颜色是填充整个画布,常用于绘制底色。

关于颜色的更多资料请参考基础篇颜色
创建画笔:
要想绘制内容,首先需要先创建一个画笔,如下:
private Paint mPaint = new Paint();
private void initPaint() {
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(10f);
}
public SloopView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
在创建完画笔之后,就可以在Canvas中绘制各种内容了。
绘制点:
可以绘制一个点,也可以绘制一组点,如下:
canvas.drawPoint(200, 200, mPaint);
canvas.drawPoints(new float[]{
500,500,
500,600,
500,700
},mPaint);
关于坐标原点默认在左上角,水平向右为x轴增大方向,竖直向下为y轴增大方向。
更多参考这里 基础篇坐标系

绘制直线:
绘制直线需要两个点,初始点和结束点,同样绘制直线也可以绘制一条或者绘制一组:
canvas.drawLine(300,300,500,600,mPaint);
canvas.drawLines(new float[]{
100,200,200,200,
100,300,200,300
},mPaint);

绘制矩形:
确定一个矩形最少需要四个数据,就是对角线的两个点的坐标值,这里一般采用左上角和右下角的两个点的坐标。
关于绘制矩形,Canvas提供了三种重载方法,第一种就是提供四个数值(矩形左上角和右下角两个点的坐标)来确定一个矩形进行绘制。
其余两种是先将矩形封装为Rect或RectF(实际上仍然是用两个坐标点来确定的矩形),然后传递给Canvas绘制,如下:
canvas.drawRect(100,100,800,400,mPaint);
Rect rect = new Rect(100,100,800,400);
canvas.drawRect(rect,mPaint);
RectF rectF = new RectF(100,100,800,400);
canvas.drawRect(rectF,mPaint);
以上三种方法所绘制出来的结果是完全一样的。

看到这里,相信很多观众会产生一个疑问,为什么会有Rect和RectF两种?两者有什么区别吗?
答案当然是存在区别的,两者最大的区别就是精度不同,Rect是int(整形)的,而RectF是float(单精度浮点型)的。除了精度不同,两种提供的方法也稍微存在差别,在这里我们暂时无需关注,想了解更多参见官方文档 Rect 和 RectF
绘制圆角矩形:
绘制圆角矩形也提供了两种重载方式,如下:
RectF rectF = new RectF(100,100,800,400);
canvas.drawRoundRect(rectF,30,30,mPaint);
canvas.drawRoundRect(100,100,800,400,30,30,mPaint);
上面两种方法绘制效果也是一样的,但鉴于第二种方法在API21的时候才添加上,所以我们一般使用的都是第一种。

下面简单解析一下圆角矩形的几个必要的参数的意思。
很明显可以看出,第二种方法前四个参数和第一种方法的RectF作用是一样的,都是为了确定一个矩形,最后一个参数Paint是画笔,无需多说,与矩形相比,圆角矩形多出来了两个参数rx 和 ry,这两个参数是干什么的呢?
稍微分析一下,既然是圆角矩形,他的角肯定是圆弧(圆形的一部分),我们一般用什么确定一个圆形呢?
答案是圆心 和 半径,其中圆心用于确定位置,而半径用于确定大小。
由于矩形位置已经确定,所以其边角位置也是确定的,那么确定位置的参数就可以省略,只需要用半径就能描述一个圆弧了。
但是,半径只需要一个参数,但这里怎么会有两个呢?
好吧,让你发现了,这里圆角矩形的角实际上不是一个正圆的圆弧,而是椭圆的圆弧,这里的两个参数实际上是椭圆的两个半径,他们看起来个如下图:

红线标注的 rx 与 ry 就是两个半径,也就是相比绘制矩形多出来的那两个参数。
我们了解到原理后,就可以为所欲为了,通过计算可知我们上次绘制的矩形宽度为700,高度为300,当你让 rx大于350(宽度的一半), ry大于150(高度的一半) 时奇迹就出现了, 你会发现圆角矩形变成了一个椭圆, 他们画出来是这样的 ( 为了方便确认我更改了画笔颜色, 同时绘制出了矩形和圆角矩形 ):
RectF rectF = new RectF(100,100,800,400);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawRoundRect(rectF,700,400,mPaint);

其中灰色部分是我们所选定的矩形,而里面的圆角矩形则变成了一个椭圆,实际上在rx为宽度的一半,ry为高度的一半时,刚好是一个椭圆,通过上面我们分析的原理推算一下就能得到,而当rx大于宽度的一半,ry大于高度的一半时,实际上是无法计算出圆弧的,所以drawRoundRect对大于该数值的参数进行了限制(修正),凡是大于一半的参数均按照一半来处理。
绘制椭圆:
相对于绘制圆角矩形,绘制椭圆就简单的多了,因为他只需要一个矩形矩形作为参数:
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);
canvas.drawOval(100,100,800,400,mPaint);
同样,以上两种方法效果完全一样,但一般使用第一种。

绘制椭圆实际上就是绘制一个矩形的内切图形,原理如下,就不多说了:

PS: 如果你传递进来的是一个长宽相等的矩形(即正方形),那么绘制出来的实际上就是一个圆。
绘制圆:
绘制圆形也比较简单, 如下:
绘制圆形有四个参数,前两个是圆心坐标,第三个是半径,最后一个是画笔。

绘制圆弧:
绘制圆弧就比较神奇一点了,为了理解这个比较神奇的东西,我们先看一下它需要的几个参数:
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {}
从上面可以看出,相比于绘制椭圆,绘制圆弧还多了三个参数:
startAngle
sweepAngle
useCenter
通过字面意思我们基本能猜测出来前两个参数(startAngle, sweepAngel)的作用,就是确定角度的起始位置和扫过角度, 不过第三个参数是干嘛的?试一下就知道了,上代码:
```
RectF rectF = new RectF(100,100,800,400);
// 绘制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,false,mPaint);
RectF rectF2 = new RectF(100,600,800,900);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF2,mPaint);
mPaint.setColor(Color.BLUE);
Canvas之绘制基本形状
在上一篇自定义View分类与流程中我们了解自定义View相关的基本知识,不过,这些东西依旧还是理论,并不能拿来(zhuang)用(B), 这一次我们就了解一些能(zhaung)用(B)的东西。
在本篇文章中,我们先了解Canvas的基本用法,最后用一个小示例来结束本次教程。
一.Canvas简介
Canvas我们可以称之为画布,能够在上面绘制各种东西,是安卓平台2D图形绘制的基础,非常强大。
一般来说,比较基础的东西有两大特点:
1.可操作性强:由于这些是构成上层的基础,所以可操作性必然十分强大。
2.比较难用:各种方法太过基础,想要完美的将这些操作组合起来有一定难度。
不过不必担心,本系列文章不仅会介绍到Canvas的操作方法,还会简单介绍一些设计思路和技巧。
二.Canvas的常用操作速查表
操作类型 |
相关API |
备注 |
绘制颜色 |
drawColor, drawRGB, drawARGB |
使用单一颜色填充整个画布 |
绘制基本形状 |
drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc |
依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
绘制图片 |
drawBitmap, drawPicture |
绘制位图和图片 |
绘制文本 |
drawText, drawPosText, drawTextOnPath |
依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
绘制路径 |
drawPath |
绘制路径,绘制贝塞尔曲线时也需要用到该函数 |
顶点操作 |
drawVertices, drawBitmapMesh |
通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用 |
画布剪裁 |
clipPath, clipRect |
设置画布的显示区域 |
画布快照 |
save, restore, saveLayerXxx, restoreToCount, getSaveCount |
依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数 |
画布变换 |
translate, scale, rotate, skew |
依次为 位移、缩放、 旋转、错切 |
Matrix(矩阵) |
getMatrix, setMatrix, concat |
实际画布的位移,缩放等操作的都是图像矩阵Matrix,只不过Matrix比较难以理解和使用,故封装了一些常用的方法。 |
PS: Canvas常用方法在上面表格中已经全部列出了,当然还存在一些其他的方法未列出,具体可以参考官方文档 Canvas
三.Canvas详解
本篇内容主要讲解如何利用Canvas绘制基本图形。
绘制颜色:
绘制颜色是填充整个画布,常用于绘制底色。

关于颜色的更多资料请参考基础篇颜色
创建画笔:
要想绘制内容,首先需要先创建一个画笔,如下:
private Paint mPaint = new Paint();
private void initPaint() {
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(10f);
}
public SloopView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
在创建完画笔之后,就可以在Canvas中绘制各种内容了。
绘制点:
可以绘制一个点,也可以绘制一组点,如下:
canvas.drawPoint(200, 200, mPaint);
canvas.drawPoints(new float[]{
500,500,
500,600,
500,700
},mPaint);
关于坐标原点默认在左上角,水平向右为x轴增大方向,竖直向下为y轴增大方向。
更多参考这里 基础篇坐标系

绘制直线:
绘制直线需要两个点,初始点和结束点,同样绘制直线也可以绘制一条或者绘制一组:
canvas.drawLine(300,300,500,600,mPaint);
canvas.drawLines(new float[]{
100,200,200,200,
100,300,200,300
},mPaint);

绘制矩形:
确定一个矩形最少需要四个数据,就是对角线的两个点的坐标值,这里一般采用左上角和右下角的两个点的坐标。
关于绘制矩形,Canvas提供了三种重载方法,第一种就是提供四个数值(矩形左上角和右下角两个点的坐标)来确定一个矩形进行绘制。
其余两种是先将矩形封装为Rect或RectF(实际上仍然是用两个坐标点来确定的矩形),然后传递给Canvas绘制,如下:
canvas.drawRect(100,100,800,400,mPaint);
Rect rect = new Rect(100,100,800,400);
canvas.drawRect(rect,mPaint);
RectF rectF = new RectF(100,100,800,400);
canvas.drawRect(rectF,mPaint);
以上三种方法所绘制出来的结果是完全一样的。

看到这里,相信很多观众会产生一个疑问,为什么会有Rect和RectF两种?两者有什么区别吗?
答案当然是存在区别的,两者最大的区别就是精度不同,Rect是int(整形)的,而RectF是float(单精度浮点型)的。除了精度不同,两种提供的方法也稍微存在差别,在这里我们暂时无需关注,想了解更多参见官方文档 Rect 和 RectF
绘制圆角矩形:
绘制圆角矩形也提供了两种重载方式,如下:
RectF rectF = new RectF(100,100,800,400);
canvas.drawRoundRect(rectF,30,30,mPaint);
canvas.drawRoundRect(100,100,800,400,30,30,mPaint);
上面两种方法绘制效果也是一样的,但鉴于第二种方法在API21的时候才添加上,所以我们一般使用的都是第一种。

下面简单解析一下圆角矩形的几个必要的参数的意思。
很明显可以看出,第二种方法前四个参数和第一种方法的RectF作用是一样的,都是为了确定一个矩形,最后一个参数Paint是画笔,无需多说,与矩形相比,圆角矩形多出来了两个参数rx 和 ry,这两个参数是干什么的呢?
稍微分析一下,既然是圆角矩形,他的角肯定是圆弧(圆形的一部分),我们一般用什么确定一个圆形呢?
答案是圆心 和 半径,其中圆心用于确定位置,而半径用于确定大小。
由于矩形位置已经确定,所以其边角位置也是确定的,那么确定位置的参数就可以省略,只需要用半径就能描述一个圆弧了。
但是,半径只需要一个参数,但这里怎么会有两个呢?
好吧,让你发现了,这里圆角矩形的角实际上不是一个正圆的圆弧,而是椭圆的圆弧,这里的两个参数实际上是椭圆的两个半径,他们看起来个如下图:

红线标注的 rx 与 ry 就是两个半径,也就是相比绘制矩形多出来的那两个参数。
我们了解到原理后,就可以为所欲为了,通过计算可知我们上次绘制的矩形宽度为700,高度为300,当你让 rx大于350(宽度的一半), ry大于150(高度的一半) 时奇迹就出现了, 你会发现圆角矩形变成了一个椭圆, 他们画出来是这样的 ( 为了方便确认我更改了画笔颜色, 同时绘制出了矩形和圆角矩形 ):
RectF rectF = new RectF(100,100,800,400);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawRoundRect(rectF,700,400,mPaint);

其中灰色部分是我们所选定的矩形,而里面的圆角矩形则变成了一个椭圆,实际上在rx为宽度的一半,ry为高度的一半时,刚好是一个椭圆,通过上面我们分析的原理推算一下就能得到,而当rx大于宽度的一半,ry大于高度的一半时,实际上是无法计算出圆弧的,所以drawRoundRect对大于该数值的参数进行了限制(修正),凡是大于一半的参数均按照一半来处理。
绘制椭圆:
相对于绘制圆角矩形,绘制椭圆就简单的多了,因为他只需要一个矩形矩形作为参数:
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);
canvas.drawOval(100,100,800,400,mPaint);
同样,以上两种方法效果完全一样,但一般使用第一种。

绘制椭圆实际上就是绘制一个矩形的内切图形,原理如下,就不多说了:

PS: 如果你传递进来的是一个长宽相等的矩形(即正方形),那么绘制出来的实际上就是一个圆。
绘制圆:
绘制圆形也比较简单, 如下:
绘制圆形有四个参数,前两个是圆心坐标,第三个是半径,最后一个是画笔。

绘制圆弧:
绘制圆弧就比较神奇一点了,为了理解这个比较神奇的东西,我们先看一下它需要的几个参数:
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {}
从上面可以看出,相比于绘制椭圆,绘制圆弧还多了三个参数:
startAngle
sweepAngle
useCenter
通过字面意思我们基本能猜测出来前两个参数(startAngle, sweepAngel)的作用,就是确定角度的起始位置和扫过角度, 不过第三个参数是干嘛的?试一下就知道了,上代码:
```
RectF rectF = new RectF(100,100,800,400);
// 绘制背景矩形
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawArc(rectF,0,90,false,mPaint);
RectF rectF2 = new RectF(100,600,800,900);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF2,mPaint);
mPaint.setColor(Color.BLUE);