android 自定义多边形,Android:自定义view之Canvas绘制图形

本文深入解析了Android中自定义View的onDraw()方法,详细介绍了如何使用Canvas进行2D图形绘制,包括绘制颜色、基本形状、图片、文本、路径等,并探讨了Paint对象在绘制过程中的作用,如画笔样式、颜色和宽度等设置,帮助开发者更好地理解和掌握自定义View的绘制技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面讲解了onMeasure,接下来讲解onDraw,onDraw主要就是绘制,也就是我们真正关心的部分,使用的是Canvas绘图。

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

}

Canvas简介

Canvas我们可以称之为画布,能够在上面绘制各种东西,是安卓平台2D图形绘制的基础,非常强大。

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绘制基本图形。

创建画笔:

要想绘制内容,首先需要先创建一个画笔,如下:

// 1.创建一个画笔

private Paint mPaint = new Paint();

// 3.在构造函数中初始化

public SloopView(Context context, AttributeSet attrs) {

super(context, attrs);

initPaint();

// 2.初始化画笔

private void initPaint() {

mPaint.setColor(Color.BLACK); //设置画笔颜色

mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充

mPaint.setStrokeWidth(10f); //设置画笔宽度为10px

}

在创建完画笔之后,就可以在Canvas中绘制各种内容了。

绘制矩形:

确定确定一个矩形最少需要四个数据,就是对角线的两个点的坐标值,这里一般采用左上角和右下角的两个点的坐标。

关于绘制矩形,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);

以上三种方法所绘制出来的结果是完全一样的。

eeaaadfac295

为什么会有Rect和RectF两种?两者有什么区别吗?

答案是肯定有区别,两者最大的区别就是精度不同,Rect是int(整形)的,而RectF是float(单精度浮点型)的。除了精度不同,两种提供的方法也稍微存在差别,想了解更多参见官方文档 Rect 和 RectF

绘制圆角矩形:

RectF rectF = new RectF(100,100,800,400);

canvas.drawRoundRect(rectF,30,30,mPaint);

eeaaadfac295

这里多出来的两个参数是椭圆的两个半径,绘制出的圆弧是椭圆的圆弧.

eeaaadfac295

红线标注的 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);

eeaaadfac295

其中灰色部分是我们所绘制的矩形(参考用),而里面的圆角矩形则变成了一个椭圆,实际上在rx为宽度的一半,ry为高度的一半时,刚好是一个椭圆,通过上面我们分析的原理推算一下就能得到,而当rx大于宽度的一半,ry大于高度的一半时,实际上是无法计算出圆弧的,所以drawRoundRect对大于该数值的参数进行了限制(修正),凡是大于一半的参数均按照一半来处理。

绘制椭圆:

相对于绘制圆角矩形,绘制椭圆就简单的多了,因为他只需要一个矩形矩形作为参数:

// 第一种

RectF rectF = new RectF(100,100,800,400);

canvas.drawOval(rectF,mPaint);

// 第二种

canvas.drawOval(100,100,800,400,mPaint);

同样,以上两种方法效果完全一样,但一般使用第一种。

eeaaadfac295

PS: 如果你传递进来的是一个长宽相等的矩形(即正方形),那么绘制出来的实际上就是一个圆。

绘制圆:

绘制圆形也比较简单, 如下:

canvas.drawCircle(500,500,400,mPaint); // 绘制一个圆心坐标在(500,500),半径为400 的圆。

绘制圆形有四个参数,前两个是圆心坐标,第三个是半径,最后一个是画笔。

eeaaadfac295

绘制圆弧:

绘制圆弧就比较神奇一点了,为了理解这个比较神奇的东西,我们先看一下它需要的几个参数:

// 第一种

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.drawArc(rectF2,0,90,true,mPaint);

上述代码实际上是绘制了一个起始角度为0度,扫过90度的圆弧,两者的区别就是是否使用了中心点,结果如下:

eeaaadfac295

相比于使用椭圆,我们还是使用正圆比较多的,使用正圆展示一下效果:

RectF rectF = new RectF(100,100,600,600);

// 绘制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF,mPaint);

// 绘制圆弧

mPaint.setColor(Color.BLUE);

canvas.drawArc(rectF,0,90,false,mPaint);

//-------------------------------------

RectF rectF2 = new RectF(100,700,600,1200);

// 绘制背景矩形

mPaint.setColor(Color.GRAY);

canvas.drawRect(rectF2,mPaint);

// 绘制圆弧

mPaint.setColor(Color.BLUE);

canvas.drawArc(rectF2,0,90,true,mPaint);

eeaaadfac295

简要介绍Paint

看了上面这么多,相信有有人会有疑问,如果我想绘制一个圆,只要边不要里面的颜色怎么办?

很简单,绘制的基本形状由Canvas确定,但绘制出来的颜色,具体效果则由Paint确定。

如果你注意到了的话,在一开始我们设置画笔样式的时候是这样的:

mPaint.setStyle(Paint.Style.FILL); //设置画笔模式为填充

为了展示方便,容易看出效果,之前使用的模式一直为填充模式,实际上画笔有三种模式,如下:

STROKE //描边

FILL //填充

FILL_AND_STROKE //描边加填充

为了区分三者效果我们做如下实验:

Paint paint = new Paint();

paint.setColor(Color.BLUE);

paint.setStrokeWidth(40); //为了实验效果明显,特地设置描边宽度非常大

// 描边

paint.setStyle(Paint.Style.STROKE);

canvas.drawCircle(200,200,100,paint);

// 填充

paint.setStyle(Paint.Style.FILL);

canvas.drawCircle(200,500,100,paint);

// 描边加填充

paint.setStyle(Paint.Style.FILL_AND_STROKE);

canvas.drawCircle(200, 800, 100, paint);

eeaaadfac295

关于Paint详细的可以看下官方介绍Paint

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值