【譯】一文帶你了解Android中23個(gè)關(guān)于Canvas繪制的方法

原作者:Elye
地址:http://suo.im/5ZrCzC
譯者:依然范特稀西

如果你想從頭開始在Android中創(chuàng)建自定義View,那么你最好先了解Canvas上有哪寫可用于繪制的方法。

在本文中,我將列出23個(gè)在Android Canvas 上可以繪制的方法,當(dāng)你看到它們時(shí),你可能會(huì)發(fā)現(xiàn)一些自己以前不知道的東西(我也對(duì)其中的一些方法感到驚訝!)

如下所示,我將它們分為了4類:

  • 1、幾何圖形繪制
  • 2、文本繪制
  • 3、顏色繪制
  • 4、圖片繪制

接下來,我們一一介紹一下這些方法。

幾何圖形繪制

多數(shù)人使用Canvas來繪制幾何圖形

1. drawLine

簡(jiǎn)單的繪制一條線

canvas.drawLine(startX, startY, endX, endY, paint)
2. drawLines

如果你想要繪制多條線,相比于多次執(zhí)行drawLine,我們推薦使用drawLines來完成,我們只需要提供一個(gè)坐標(biāo)值的平面float數(shù)組列表,如下所示。

canvas.drawLines(
    floatArrayOf(
        startFirstX, startFirstY, endFirstX, endFirstY,
        startSecondX, startSecondY, endSecondX, endSecondY),
    paint)
3. drawPoint

雖然您可以通過以相同的起點(diǎn)和終點(diǎn)坐標(biāo)畫一條線來畫點(diǎn),這是一種技巧。我們可以使用專門提供的繪制點(diǎn)的方法,drawPoint函數(shù)。

canvas.drawPoint(coordinateX, coordinateY, paint)
4. drawPoints

lines一樣,你可以通過提供一個(gè)平面坐標(biāo)數(shù)組來繪制多個(gè)點(diǎn)。

canvas.drawPoints(
    floatArrayOf(
        startX, startY,
        startSecondX, startSecondY),
    paint)
5. drawRect

使用坐標(biāo)或Rect類繪制矩形。

canvas.drawRect(
    Rect(startX, topY, endX, bottomY), 
    paint)
6. drawRoundRect

如果你想要繪制一個(gè)圓角矩形,可以使用drawRoundRect,它和drawRect法法很像,但是增加了兩個(gè)參數(shù)radiusXradiusY來定義圓角的彎曲程度。

canvas.drawRoundRect(rect, radiusX, radiusY, projectResources.paint)

如果radiusX等于radiusY,它將繪制均勻的圓角。

當(dāng)radiusX = radiusY時(shí),它將具有常規(guī)的圓角,如下所示:

如果radiusX 大于 radiusY 時(shí),就會(huì)出現(xiàn)下面這樣的效果:

如果radiusX 小于 radiusY 時(shí),又變成了這樣:

7. drawCircle

drawCircle非常簡(jiǎn)單,它只需要一個(gè)圓心坐標(biāo)和半徑。

canvas.drawCircle(
    centerCoordinateX, centerCoordinateY,
    radius,
    paint)
8. drawOval

不像繪制圓形那樣,繪制橢圓時(shí),我們不需要提供半徑,而是提供一個(gè)rect,然后橢圓就會(huì)被正確繪制

canvas.drawOval(rect, paint)
9. drawArc

繪制弧形和繪制橢圓時(shí)一樣的機(jī)制,使用rect,它還增加了幾個(gè)參數(shù):startAnglesweepAngleuseCenter。

canvas.drawArc(rect, startAngle, sweepAngle, useCenter, paint)

對(duì)于startAngle,將rect的中間端作為起點(diǎn),即順時(shí)針90°。從那里開始,startAngle被認(rèn)為是。然后從startAngle計(jì)算sweepAngle。兩者都使用角度度°值。

useCenter是一個(gè)布爾變量,用于確定圓弧是否連接到中心。下圖說明了useCenterfalsetrue之間的區(qū)別。

useCenter = false:

useCenter = true :

10. drawPath

有時(shí)候,我們想畫一些不限于普通幾何線的東西,我們可以使用drawPath,這里的Path是一個(gè)包含了我們想要繪制路徑的一個(gè)對(duì)象,它由鉛筆畫和移動(dòng)之類的功能如moveTolineTo組成。

以下是我們繪制十字標(biāo)記的路徑的示例

val path = Path()
path.moveTo(startX, topY)
path.lineTo(endX, bottomY)
path.moveTo(startX, bottomY)
path.lineTo(endX, topY)
canvas.drawPath(path, paint)

drawPath是一個(gè)非常有用的功能。許多人使用它在Android中制作繪圖應(yīng)用程序。

11. drawVertices

這是一個(gè)相對(duì)復(fù)雜的函數(shù),它以最小的點(diǎn)繪制三角形或頂點(diǎn)。例如,使用六個(gè)坐標(biāo),一個(gè)可以繪制四個(gè)三角形:

重復(fù)使用時(shí),可用于復(fù)雜的3D建模。下面的藝術(shù)品(3D玫瑰)是使用drawVertices繪制的。
[圖片上傳失敗...(image-230e40-1583247600593)]

更詳細(xì)的說明可以看:https://proandroiddev.com/playing-with-android-canvas-drawvertices-32266c480ab6

Text Drawing

如果我們必須自己繪制文本,那將是非常棘手的。幸運(yùn)的是,我們有幾個(gè)不錯(cuò)的選擇:

12. drawText

在Android中,我們一般使用TextView 來顯示文本,但是如果你要更好的控制文本的話,如:動(dòng)態(tài)更換,精準(zhǔn)定位等等。Canvas的drawText就派上了用場(chǎng)。

方法如下,有textcoordinatepaint。

canvas.drawText(text, coordinateX, coordinateY, paintText)

如果設(shè)置正確,這些將很有趣,如下所示

[圖片上傳失敗...(image-7be96a-1583247600593)]

13. Draw StaticLayout

drawText有局限性。它不會(huì)將較長(zhǎng)的單詞包裝到第二行。它也不處理/n進(jìn)位返回

因此,我們需要一個(gè)可將長(zhǎng)字換行的文本到第二行來繪制的StaticLayout 。

StaticLayout實(shí)際上并不是Canvas的繪制函數(shù),而是將自身繪制到畫布中。下面是它的繪制方式:

val staticLayout =
    StaticLayout.Builder.obtain(
        TEXT, 0, TEXT.length, textPaint, width
    ).build()

canvas.save()
canvas.translate(coordinateX, coordinateY)
staticLayout.draw(canvas)
canvas.restore()

結(jié)果如下:

14. drawPosText

drawPosText使每個(gè)字符都可以放置在指定位置。在下面,單詞fly被寫在不同的Y位置。

API如下所示:

val posArray = listOf(x1, y1, x2, y2, x3, y3 ...).toFloatArray()
canvas.drawPosText(TEXT, startIndex, endIndex, posArray, paint)

?

提供的坐標(biāo)點(diǎn)必須至少與要繪制的字母相同,否則將崩潰。文檔說明:

[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

在繪制文本的基礎(chǔ)上加上一個(gè)路徑,我們就可以沿著提供的path來繪制文本,xy的位置相對(duì)于path給定的位置。

canvas.drawTextOnPath(TEXT, path, x, y, paint)

下面是一個(gè)V字行的路徑,我們沿著path繪制文本。

16. drawTextRun

這個(gè)繪制方法就有點(diǎn)復(fù)雜了,因?yàn)樗ǔ2慌c英語(yǔ)單詞一起使用。它僅適用于其字母根據(jù)周圍字母的可見性而繪制不同的語(yǔ)言。

例如,下圖有兩行兩個(gè)字母。這兩行中的兩個(gè)字母相同。但是,它們的寫法不同。在第一行中,它們是較大單詞的一部分,而在第二行中,則分別聲明了兩個(gè)字母。

Color Drawing

上色對(duì)于我們正在繪制的畫布的前景和背景很有用。一起來看看吧...

17. drawRGB

這個(gè)方法僅是在畫布canvas上繪制顏色,這對(duì)于設(shè)置背景色非常有用

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.

這對(duì)于設(shè)置正面顏色并使后面的項(xiàng)目變暗很有用。

正常圖片:

設(shè)置了紅色透明度的圖片:

19. drawColor

使用這個(gè)方法,我們可以使用顏色資源來代替ARGB顏色,用下面這個(gè)API:

canvas.drawColor(context.getColor(R.color.colorPrimary))
20. drawPaint

有時(shí),我們喜歡畫一些奇特的顏色。代替使用ARGB或資源顏色,我們可以創(chuàng)建一個(gè)Paint對(duì)象。下面是一個(gè)示例:

val gradientPaint by lazy {
    Paint().apply {
        shader = RadialGradient(
            width/2f,
            height/2f,
            height/2f,
            Color.GREEN,
            Color.RED,
            Shader.TileMode.MIRROR
        )
    }
canvas.drawPaint(gradientPaint)

繪制圖片

如果無法加載圖像以進(jìn)行繪制和處理,則cavans繪制將是不完整的。因此,讓我們探索一下我們可以做些啥。

21. drawBitmap

給一個(gè)bitmap,我們可以將它繪制到畫布上

private val bitmap by lazy {
    BitmapFactory.decodeResource(resources, R.drawable.image)
}
canvas.drawBitmap(bitmap, sourceRect, destRect, paint)

必須的參數(shù)是bitmapdestRect:

  • bitmap 可以從資源文件加載
  • destRect 是畫布上將要繪制的矩形區(qū)域

可選擇的參數(shù)(可以為null)是sourceRectpaint

  • sourceRect是一個(gè)矩形,代表要繪制圖片的哪個(gè)子集。如果為空,則拍攝整個(gè)照片(注意:這對(duì)于某些動(dòng)畫非常有用,比如要添加整個(gè)動(dòng)畫圖形的圖片,并且一次只顯示一個(gè)子集時(shí)。)
  • paint可以設(shè)置為null,并且位圖將照常繪制。如果我們計(jì)劃用另一幅圖像將其遮蔽,則paint很有用。此StackOverflow中顯示了一個(gè)示例:https://stackoverflow.com/questions/23966272/android-mask-bitmap-on-canvas-gen-a-black-space/26031133#26031133
22. drawPicture

如果你想要繪制的東西組合在一起,并且要多次執(zhí)行,并且您不希望處理變慢并且必須重新繪制每個(gè)時(shí)間,則可以將整個(gè)圖形放入“圖片(Picture)”中。

下面是一個(gè)簡(jiǎn)單的示例,其中我們將圖形存儲(chǔ)到圖片中:

private val picture by lazy {
    val picture = Picture()
    val pCanvas = picture.beginRecording(width, height)
    pCanvas.drawBitmap(bitmap, null, rect, null)
    picture.endRecording()
    picture
}

需要時(shí),只需執(zhí)行這行代碼:

canvas.drawPicture(picture)

這樣可以加快整個(gè)繪制過程的速度,以完成需要一遍又一遍的繪制。

23. drawBitmapMesh

這是為了操縱繪制的位圖圖像。給定一個(gè)圖像,我們可以在圖像內(nèi)設(shè)置坐標(biāo),然后將一個(gè)點(diǎn)平移到另一個(gè)位置,從而轉(zhuǎn)換它的圖像。

例如。下圖的中心X,Y顯示在白線橫截面中。

然而,使用drawBitmapMesh,我們可以移動(dòng)坐標(biāo)并相應(yīng)地變換圖像。

可以看下這篇博客了解詳情;https://proandroiddev.com/transforming-picture-with-android-canvas-drawbitmapmesh-35f359235774

所有示例代碼可以看Github:https://github.com/elye/demo_android_canvas_draw

玩轉(zhuǎn)Android ``Canvas繪圖吧!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容