天天看點

為什麼 Android 上 Canvas 畫出的圖形不夠平滑

<b>本文講的是為什麼 Android 上 Canvas 畫出的圖形不夠平滑,</b>

<b></b>

通過 Google 搜尋我們很快就能找到這個在 StackOverflow 中被問了很多次的問題,同時答案也經常是相同的:你需要給你的 Paint 對象設定 ANTI_ALIAS_FLAG 屬性。但對于大多數人來說這并不能解決問題。下面我講講原因。

若你需要在 Canvas 上繪制,你有兩種選擇。

直接在 Canvas 上繪制。

先在 Bitmap 上繪制再将 Bitmap 繪制到 Canvas 上。

在你繪制前,先設定 Paint 對象的 ANTI_ALIAS_FLAG 屬性可以得到平滑的圖形。

你有兩種設定 ANTI_ALIAS_FLAG 屬性的方式:

然後通過下面代碼直接在 Canvas 上繪制。

為什麼 Android 上 Canvas 畫出的圖形不夠平滑

直接在 Canvas 上繪制

正如你看到的,設定 ANTI_ALIAS_FLAG 屬性可以産生平滑的邊緣。**這裡它能起作用是因為預設下每當 onDraw 被調用時系統先将 Canvas 清空然後重繪所有東西。**當我在下文詳細讨論 ANTI_ALIAS_FLAG 的工作原理時, 你會意識到這段資訊的重要性。

如果你需要儲存這張被繪制的圖形,或者你需要繪制透明的像素,有個很好的辦法是先将圖形繪制到 Bitmap 上然後再将 Bitmap 繪制到 Canvas 上。下面我們通過代碼來實作它。

注意: 在 onDraw 方法中初始化 Bitmap 并不是一個好主意,但在這裡可以增加代碼可讀性。

此方式實作效果如下,沒有設定 ANTI_ALIAS_FLAG 的圖像不夠平滑,而設定了該屬性的更好一點,但你還是能發現它的邊緣是粗糙的。

為什麼 Android 上 Canvas 畫出的圖形不夠平滑

先在 Bitmap 上繪制再将 Bitmap 繪制到 Canvas 上

我們很容易會忽視上面代碼片段出現的問題。即雖然每次 onDraw 被調用時都會更新你在 Bitmap 上繪制的圓形,但理論上說,你隻是在上一個圖檔上重繪。是以這個問題的答案是 ANTI_ALIAS_FLAG 到底是怎麼工作的?

簡單來說,ANTI_ALIAS_FLAG 通過混合前景色與背景色來産生平滑的邊緣。在我們的例子中,背景色是透明的而前景色是紅色的,ANTI_ALIAS_FLAG 通過将邊緣處像素由純色逐漸轉化為透明來讓邊緣看起來是平滑的。

而當我們在 Bitmap 上重繪時,像素的顔色會越來越純粹導緻邊緣越來越粗糙。在下面這張圖檔中,我們看下不斷重繪 50% 透明度的紅色會出現什麼狀況。正如你看到的,隻需三次重繪,顔色就十分接近純色了。這就是為什麼設定了 ANTI_ALIAS_FLAG 後你們圖形的邊緣還是十分粗糙。

<a href="https://camo.githubusercontent.com/168092781181638a260b252970a86bca46bb4039/687474703a2f2f7777342e73696e61696d672e636e2f6c617267652f613439303134376667773166337064317a616d746a6a3230623430356b6139762e6a7067" target="_blank"></a>

這裡有兩個選擇。

避免重繪。

在重繪前清空你的 Bitmap。

下面我修改了上文的代碼,添加一行代碼讓它在每次重繪前先清空 Bitmap。當然,如果你覺得純色更加符合你的需求的話,你也可以不用每次都清空 Bitmap。

現在, Bitmap 會在每次重繪前先清空。下面的圖檔就是代碼更改後的效果。

<a href="https://camo.githubusercontent.com/0ebf8bcc85cd471439dc11ce21f8dcd7916a8cf1/687474703a2f2f7777342e73696e61696d672e636e2f6c617267652f6134393031343766677731663370643263686566656a3230386330686d7133672e6a7067" target="_blank"></a>

注意: 如果不需要經常修改 Bitmap,你可以隻(在 if 條件語句中)初始化并繪制 Bitmap 一次,然後在 onDraw 方法中将其繪制到 Canvas 上,這樣能保證更好的性能。也意味着頻繁地清空像素并繪制圓形的操作是沒有必要的。

如需要先繪制到 Bitmap 上:

你想儲存圖像。

你想繪制透明的像素。

你的圖像不需要經常改變并且/或者需要耗時操作。

通過設定 ANTI_ALIAS_FLAG 屬性繪制平滑的邊緣。

避免在 Bitmap 上重繪,或者在重繪前先清空 Bitmap。

<b>原文釋出時間為:2016年06月12日</b>

<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>

繼續閱讀