【译】一文带你了解Android中23个关于Canvas绘制的方法
原作者:Elye
地址:http://suo.im/5ZrCzC
译者:依然范特稀西
如果你想从头开始在Android中创建自定义View,那么你最好先了解Canvas上有哪写可用于绘制
的方法。
在本文中,我将列出23个
在Android Canvas 上可以绘制的方法,当你看到它们时,你可能会发现一些自己以前不知道的东西(我也对其中的一些方法感到惊讶!)
如下所示,我将它们分为了4类:
- 1、几何图形绘制
- 2、文本绘制
- 3、颜色绘制
- 4、图片绘制
接下来,我们一一介绍一下这些方法。
几何图形绘制
多数人使用Canvas来绘制几何图形
1. drawLine
简单的绘制一条线
canvas.drawLine(startX, startY, endX, endY, paint)
2. drawLines
如果你想要绘制多条线,相比于多次执行drawLine
,我们推荐使用drawLines
来完成,我们只需要提供一个坐标值的平面float
数组列表,如下所示。
canvas.drawLines(
floatArrayOf(
startFirstX, startFirstY, endFirstX, endFirstY,
startSecondX, startSecondY, endSecondX, endSecondY),
paint)
3. drawPoint
虽然您可以通过以相同的起点和终点坐标画一条线来画点,这是一种技巧。我们可以使用专门提供的绘制点的方法,drawPoint
函数。
canvas.drawPoint(coordinateX, coordinateY, paint)
4. drawPoints
和lines
一样,你可以通过提供一个平面坐标数组来绘制多个点。
canvas.drawPoints(
floatArrayOf(
startX, startY,
startSecondX, startSecondY),
paint)
5. drawRect
使用坐标或Rect
类绘制矩形。
canvas.drawRect(
Rect(startX, topY, endX, bottomY),
paint)
6. drawRoundRect
如果你想要绘制一个圆角矩形,可以使用drawRoundRect
,它和drawRect
法法很像,但是增加了两个参数radiusX
和radiusY
来定义圆角的弯曲程度。
canvas.drawRoundRect(rect, radiusX, radiusY, projectResources.paint)
如果radiusX
等于radiusY
,它将绘制均匀的圆角。
当radiusX = radiusY
时,它将具有常规的圆角,如下所示:
如果radiusX
大于 radiusY
时,就会出现下面这样的效果:
如果radiusX
小于 radiusY
时,又变成了这样:
7. drawCircle
drawCircle
非常简单,它只需要一个圆心坐标和半径。
canvas.drawCircle(
centerCoordinateX, centerCoordinateY,
radius,
paint)
8. drawOval
不像绘制圆形那样,绘制椭圆时,我们不需要提供半径,而是提供一个rect
,然后椭圆就会被正确绘制
canvas.drawOval(rect, paint)
9. drawArc
绘制弧形和绘制椭圆时一样的机制,使用rect
,它还增加了几个参数:startAngle
,sweepAngle
和useCenter
。
canvas.drawArc(rect, startAngle, sweepAngle, useCenter, paint)
对于startAngle
,将rect
的中间端作为起点,即顺时针90°
。从那里开始,startAngle
被认为是0°
。然后从startAngle
计算sweepAngle
。两者都使用角度度°
值。
useCenter
是一个布尔变量,用于确定圆弧是否连接到中心。下图说明了useCenter
为false
和true
之间的区别。
useCenter = false
:
useCenter = true
:
10. drawPath
有时候,我们想画一些不限于普通几何线的东西,我们可以使用drawPath
,这里的Path
是一个包含了我们想要绘制路径的一个对象,它由铅笔画和移动之类的功能如moveTo
和lineTo
组成。
以下是我们绘制十字标记的路径的示例
val path = Path()
path.moveTo(startX, topY)
path.lineTo(endX, bottomY)
path.moveTo(startX, bottomY)
path.lineTo(endX, topY)
canvas.drawPath(path, paint)
drawPath
是一个非常有用的功能。许多人使用它在Android中制作绘图应用程序。
11. drawVertices
这是一个相对复杂的函数,它以最小的点绘制三角形或顶点。例如,使用六个坐标,一个可以绘制四个三角形:
重复使用时,可用于复杂的3D建模。下面的艺术品(3D玫瑰)是使用drawVertices
绘制的。
[图片上传失败...(image-230e40-1583247600593)]
更详细的说明可以看:https://proandroiddev.com/playing-with-android-canvas-drawvertices-32266c480ab6
Text Drawing
如果我们必须自己绘制文本,那将是非常棘手的。幸运的是,我们有几个不错的选择:
12. drawText
在Android中,我们一般使用TextView
来显示文本,但是如果你要更好的控制文本的话,如:动态更换,精准定位等等。Canvas的drawText
就派上了用场。
方法如下,有text
,coordinate
和paint
。
canvas.drawText(text, coordinateX, coordinateY, paintText)
如果设置正确,这些将很有趣,如下所示
[图片上传失败...(image-7be96a-1583247600593)]
13. Draw StaticLayout
drawText
有局限性。它不会将较长的单词包装到第二行。它也不处理/n
进位返回
因此,我们需要一个可将长字换行的文本到第二行来绘制的StaticLayout
。
StaticLayout实际上并不是Canvas的绘制函数,而是将自身绘制到画布中。下面是它的绘制方式:
val staticLayout =
StaticLayout.Builder.obtain(
TEXT, 0, TEXT.length, textPaint, width
).build()
canvas.save()
canvas.translate(coordinateX, coordinateY)
staticLayout.draw(canvas)
canvas.restore()
结果如下:
14. drawPosText
drawPosText
使每个字符都可以放置在指定位置。在下面,单词fly
被写在不同的Y
位置。
API如下所示:
val posArray = listOf(x1, y1, x2, y2, x3, y3 ...).toFloatArray()
canvas.drawPosText(TEXT, startIndex, endIndex, posArray, paint)
提供的坐标点必须至少与要绘制的字母相同,否则将崩溃。文档说明:
[This API is deprecated] because this method does not support glyph composition and decomposition and should therefore not be used to render complex scripts. It also doesn’t handle supplementary characters
15. drawTextOnPath
在绘制文本的基础上加上一个路径,我们就可以沿着提供的path
来绘制文本,x
和y
的位置相对于path
给定的位置。
canvas.drawTextOnPath(TEXT, path, x, y, paint)
下面是一个V字行的路径,我们沿着path
绘制文本。
16. drawTextRun
这个绘制方法就有点复杂了,因为它通常不与英语单词一起使用。它仅适用于其字母根据周围字母的可见性而绘制不同的语言。
例如,下图有两行两个字母。这两行中的两个字母相同。但是,它们的写法不同。在第一行中,它们是较大单词的一部分,而在第二行中,则分别声明了两个字母。
Color Drawing
上色对于我们正在绘制的画布的前景和背景很有用。一起来看看吧...
17. drawRGB
这个方法仅是在画布canvas
上绘制颜色,这对于设置背景色非常有用
canvas.drawRGB(red, green, blue)
// Each is between 0 and 255, where 0 is not there, and 255 is full.
// When alpha is 255, it is opaque, and 0 is transparent.
18. drawARGB
和drawRGB
相似,drawARGB
增加了使颜色有透明度的能力。
canvas.drawARGB(alpha, red, green, blue)
// When alpha is 255, it is opaque, and 0 is transparent.
这对于设置正面颜色并使后面的项目变暗很有用。
正常图片:
设置了红色透明度的图片:
19. drawColor
使用这个方法,我们可以使用颜色资源
来代替ARGB
颜色,用下面这个API:
canvas.drawColor(context.getColor(R.color.colorPrimary))
20. drawPaint
有时,我们喜欢画一些奇特的颜色。代替使用ARGB
或资源颜色,我们可以创建一个Paint
对象。下面是一个示例:
val gradientPaint by lazy {
Paint().apply {
shader = RadialGradient(
width/2f,
height/2f,
height/2f,
Color.GREEN,
Color.RED,
Shader.TileMode.MIRROR
)
}
canvas.drawPaint(gradientPaint)
绘制图片
如果无法加载图像以进行绘制和处理,则cavans
绘制将是不完整的。因此,让我们探索一下我们可以做些啥。
21. drawBitmap
给一个bitmap
,我们可以将它绘制到画布上
private val bitmap by lazy {
BitmapFactory.decodeResource(resources, R.drawable.image)
}
canvas.drawBitmap(bitmap, sourceRect, destRect, paint)
必须的参数是bitmap
和 destRect
:
-
bitmap
可以从资源文件加载 -
destRect
是画布上将要绘制的矩形区域
可选择的参数(可以为null
)是sourceRect
和paint
:
-
sourceRect
是一个矩形,代表要绘制图片的哪个子集。如果为空,则拍摄整个照片(注意:这对于某些动画非常有用,比如要添加整个动画图形的图片,并且一次只显示一个子集时。) -
paint
可以设置为null,并且位图将照常绘制。如果我们计划用另一幅图像将其遮蔽,则paint很有用。此*
中显示了一个示例:https://*.com/questions/23966272/android-mask-bitmap-on-canvas-gen-a-black-space/26031133#26031133
22. drawPicture
如果你想要绘制的东西组合在一起,并且要多次执行,并且您不希望处理变慢并且必须重新绘制每个时间,则可以将整个图形放入“图片(Picture)”中。
下面是一个简单的示例,其中我们将图形存储到图片中:
private val picture by lazy {
val picture = Picture()
val pCanvas = picture.beginRecording(width, height)
pCanvas.drawBitmap(bitmap, null, rect, null)
picture.endRecording()
picture
}
需要时,只需执行这行代码:
canvas.drawPicture(picture)
这样可以加快整个绘制过程的速度,以完成需要一遍又一遍的绘制。
23. drawBitmapMesh
这是为了操纵绘制的位图图像。给定一个图像,我们可以在图像内设置坐标,然后将一个点平移到另一个位置,从而转换它的图像。
例如。下图的中心X,Y显示在白线横截面中。
然而,使用drawBitmapMesh
,我们可以移动坐标并相应地变换图像。
可以看下这篇博客了解详情;https://proandroiddev.com/transforming-picture-with-android-canvas-drawbitmapmesh-35f359235774
所有示例代码可以看Github:https://github.com/elye/demo_android_canvas_draw
玩转Android ``Canvas
绘图吧!