国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Canvas使用 -- 在canvas上繪制圓角矩形并添加文字

2019-11-09 18:20:48
字體:
來源:轉載
供稿:網友

前言

先來閑聊一下寫這個題目的原因吧,其實這個知識點對于大神來說其實是很簡單的,所以如果大神看到這里的話,其實就可以不用看下去了。至于如果是新手,或者說跟本人一樣,對于canvas的操作還有疑惑的朋友,希望你可以從這篇文章中得到你想要的答案,同時可以解決你的問題。 其實這個文章源自于最近項目需要重構,不得不說,作為一個邁過十年時光的項目來說,要進行重構還是比較煩惱的,至于這個煩惱的原因吧,不用多說,大家也應該知道在產品X閑著沒事,正在為自己的KPI而擔心的時候,總想搞點事情,這也是無可厚非,尤其是一個菜鳥產品X急切需要表現的時候。當然了,話雖這么說,但是能夠為這個有十年光景的項目進行一次重構,心里還是有點小激動的,畢竟能夠吸收前人的思想,同時自己又可以在項目中大展身手,對自己來說也是好的。 那么我就來說說這個需求吧,因為我們應用是小說閱讀器,所以自然閱讀頁上面肯定是重中之重,而這一塊在性能上的要求無疑也是比較高的,如果單純使用各種View的組合成為一個新的View,明顯這樣也是可以的,但是這樣的性能必然不是很好,因為這里涉及到多層View的嵌套操作,同時對視圖的過度渲染也會導致卡慢等的情況出現,所以最好的方式我們最好還是通過在canvas進行操作了。當然這里我給出的只是canvas操作中的一個我遇到問題時的操作,這些問題可能在大牛看來不值一提,但是哪個敢說未來的大牛不會踩一下坑呢?所以我就只能給自己這樣的小白歸納一下自己的問題了,當然由于是重構項目,后續肯定還會有各種各樣的問題,所以如果有興趣的朋友可以關注我的博客,后續我會將我重構中的問題一一收集。

正文

首先我們先來看看canvas的一些基本的常用的操作

操作類型 相關API 備注
繪制顏色 drawColordrawRGBdrawARGB 使用單一顏色填充canvas
繪制基本形狀 drawPointdrawPointsdrawLinedrawLinesdrawRectdrawRoundRectdrawOval,drawCircle,drawArc 依次是點、線、矩形、圓角矩形橢圓、圓、圓弧
繪制圖片 drawBitmap,drawPicture 繪制位圖和圖片
繪制文本 drawText,drawPostTextdrawTextOnPath 依次是繪制文字、繪制文字時根據制定每個文字位置、根據路徑繪制文字
繪制路徑 drawPath 繪制路徑,繪制貝塞爾曲線時也需要用到該函數
頂點操作 drawVerticesdrawBitmapMesh 通過對頂點操作可以使圖像形變,drawVertices直接對畫布作用、drawBitmapMesh只對繪制的bitmap作用
畫布裁剪 clipPath,cliPRect 設置畫布的顯示區域
畫布快照 save,restore,saveLayerXxx,restoreToCount,getSaveCount 依次是保存當前狀態、回滾到上一次保存的狀態、保存圖層狀態、回滾到制定狀態、獲取保存次數
畫布變換 translate,scale,rotate,skew 依次是位移、縮放、旋轉、錯切
Matrix矩陣 getMatrix,setMatrix,concat 實際上畫布的位移,縮放等操作的都是圖像矩陣Matrix,只不過Matrix比較難以理解故封裝了一些常用的方法

當然這么多的操作,其實都只是列舉,實際上這篇文章中,我們用到的僅僅只是drawRoundRect以及drawText而已,其他的操作可以在網上查找更多的資料自行了解,當然也可以繼續關注我的后續文章。

NeoBosco 上圖是我們想要實現的結果,當然看到這個圖的時候,肯定很多人會覺得這樣做其實很簡單,不就是繪制一個圓角的矩形,然后通過計算坐標的方式,將文本繪制到矩形的居中位置就好了。好吧,我承認我當時也就是這么想的,但是在我這么甘的時候問題就來了。

使用drawRoundRect()和drawText()繪制時總會出現莫名其妙的偏差

float startX = 100 ;float startY = 100 ;float endX = 600 ;float endY = 200 ;RectF rectF = new RectF(startX, startY, endX, endY);canvas.drawRoundRect(rectF, 20, 20, mButtonPaint);

首先我們通過上面代碼在canvas上繪制出一個圓角的矩形。說到這里就要提一句,canvas.drawRoundRect()有兩個不同參的函數,因為博主的項目中需要兼容較低的android系統版本,所以采用上面比較通用的繪制圓角矩形的API。當然這里可能還有一些讀者會問Rect和RectF的區別,這個其實度娘一下就已經有很多答案了,博主就不詳述了,它代表了坐標系內某一塊矩形區域的參數封裝,而Rect跟RectF區別在于得到的值的精度問題以及部分API的不同。

String text = "購買本章" ;Paint.FontMetrics fontMetrics = mButtonTextPaint.getFontMetrics();canvas.drawText(text, (endX - startX) / 2 + startX , (fontMetrics.bottom - fontMetrics.top) / 2 + startY , mButtonTextPaint);

接著通過上面的代碼,在圓角矩形的居中的位置繪制文本,這里的計算比較簡單,就是通過畫筆Paint.FontMetrics對文本進行計算。 繪制的文本的X坐標 = (結束的X坐標 - 起始的X 坐標) / 2 + 起始坐標。 繪制文本的Y坐標 = (文本的bottom坐標 - 文本的top坐標) / 2 + 起始的Y坐標。

NeoBosco

本來以為萬無一失的情況,卻想不到來了一記晴天霹靂,這蛋疼的位置是什么鬼情況。。。。 當然面對這樣的一種情況,還不至于讓我們覺得蛋疼,畢竟調這東西改改算式就好了,慢慢調就好,然!而!事情并沒有那么簡單,我一開始認為是計算的問題,而后有認為會不會是drawRoundRectdrawText是不是使用的坐標不是同一個,為何出現了這樣的偏差呢??但是想想,雖然我大天朝不能用 Google ,但是也不至于這么蛋疼整我們這些小資程序員吧,所以就想了個測試的方法,就是將文本跟的起始坐標跟圓角矩形的起始坐標設置成一樣,這樣不就能排除問題了嗎?

String text = "購買本章" ;Paint.FontMetrics fontMetrics = mButtonTextPaint.getFontMetrics();canvas.drawText(text, startX, startY, mButtonTextPaint);

然后就將繪制文本的代碼的X,Y坐標改成跟RoundRect的X,Y坐標一致。 然!而! NeoBosco

WTF~~這是什么鬼。。為什么即使設置成一樣的X,Y坐標卻相差那么遠,這不是瞎搞嗎?來到這個地步,難道還敢說這坑爹的不是兩種不同的坐標系? 然!而!峰回路轉的是,這還真不是兩個坐標系不同,這里面還有一個坑爹的知識點,就是baseline的概念,什么是baseline?就是所謂的基線了,至于概念這里就長篇大論了,這個在度娘上面,你找到的解釋簡直是多如繁星。接著,我們知道問題可能在文本的baseline上面的話,我們就可以嘗試一下這個問題了。

Paint.FontMetrics fontMetrics = mButtonTextPaint.getFontMetrics();float baseline = (rectF.bottom + rectF.top - fontMetrics.bottom - fontMetrics.top) / 2;canvas.drawText(text, rectF.centerX(), baseline, mButtonTextPaint);

所以這里我就將baseline進行重新計算,然后再一次繪制文本。。

NeoBosco

我們驚訝的發現,問題就這么容易就被解決了,而這算式在度娘上也是能夠找到,所以也就不解釋了,到此本文所說的問題也就解決了,希望能夠幫到大家,謝謝!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 博客| 滨海县| 贵溪市| 海伦市| 万全县| 南华县| 龙口市| 江城| 丹东市| 射阳县| 黑山县| 新沂市| 罗山县| 清丰县| 鹰潭市| 崇明县| 美姑县| 永州市| 宁阳县| 岢岚县| 广灵县| 应城市| 德昌县| 浙江省| 高密市| 墨竹工卡县| 满城县| 浏阳市| 中西区| 正安县| 日喀则市| 乌什县| 西宁市| 乐山市| 安福县| 德清县| 北安市| 台东市| 霸州市| 泰顺县| 丹寨县|