前言:有經驗的Android開發者,應該都會遇到在自定義View的時候,在View的某個地方寫文字,那麼當你在自定義的View中寫文字的時候,可以作到定點寫文字嗎?可以指哪寫哪嗎?寫出來的文字的位置和本身想要的位置同樣嗎?即便你最後寫的文字的位置和本身想象的位置是同樣的,那麼你知道其中的原理嗎?若是其中有一個你不能回答出來,那就認真的閱讀本文吧!本文會給出你想要的答案...java
看下下面的圖,假以下面的圖是咱們要作出的效果canvas
很簡單,有沒有?就是在一個圓的中心寫文字。紅色的圓形很好畫出來,那麼咱們怎麼將文字寫在圓的中心點上呢?第一時間想到的是拿到圓中心點的座標,而後直接調用drawText()
方法來寫文字。實現的代碼大體以下ide
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int measuredHeight = getMeasuredHeight();
int measuredWidth = getMeasuredWidth();
//cx,cy爲圓的中心點的座標
int cx = measuredWidth / 2;
int cy = measuredHeight / 2;
canvas.drawCircle(cx, cy, mRadius, mPaint);
mPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.sp18));
mPaint.setColor(Color.WHITE);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setStrokeWidth(getResources().getDimensionPixelSize(R.dimen.dp1));
canvas.drawText("wizardev", cx, cy, mPaint);
}
複製代碼
如今,看下上面代碼實現的效果spa
上圖中的黃線是在圓的中心點畫的線,能夠發現上面代碼實現的效果,明顯不是咱們想要的效果,爲何會這樣呢?下文會給出答案。code
在Android中自定義View的時候,怎麼讓系統知道應該在哪裏畫出咱們想要的圖形呢?好比畫上面的圓,這時咱們就要告訴系統,咱們要畫的圓形的圓心在什麼位置,告訴系統咱們想要的圓的半徑是多少,而後系統就能在合適的位置畫出你想要的圓了。一樣,在畫文字的時候咱們要指定文字在什麼位置,而指定的座標的位置就是文字的基線。cdn
要理解drawText()
中的基線是什麼,須要先了解一下darwText()
方法,darwText()
方法有四個參數,以下對象
drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
複製代碼
第一個參數爲你想要寫的內容,第二個參數爲文字開始的X軸座標,第三個參數爲文字開始的Y軸座標,第四個參數爲畫筆。以第二個第三個參數畫的一條水平線,就是drawText()
的基線。如上文中的第二張圖,黃色的線即爲drawText()
基線,blog
注:第二和第三個參數不必定爲文字開始的座標,也可能爲文字中心的座標或則文字結尾的座標,具體是哪一種座標與Paint
中的setTextAlign()
方法有關。開發
能夠得出結論,只要肯定了基線的位置就肯定了要畫的文字的位置了。那麼給定一個座標,怎麼肯定基線的位置呢?其實畫文字的時候,除了基線之外,還有其餘幾條線,其餘幾條線的位置以下圖get
這幾條線的意義分別是:
這幾條線的位置能夠經過FontMetrics
對象得到。
描述給定文本的各類度量值的類,它有五個成員變量,分別爲top
、ascent
、descent
、bottom
、leading
。這幾個成員變量的值都是相對基線位置的距離,如:
FontMetrics.top = top的Y座標 - 基線
想要獲取FontMetrics,能夠經過getFontMetrics()
方法獲取,具體代碼以下
Paint mPaint = new Paint()
mPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.sp18));
mPaint.setColor(Color.WHITE);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setStrokeWidth(1);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
複製代碼
使用FontMetrics獲取到的top
、ascent
、descent
、bottom
、leading
成員變量的值,是相對於基線的距離,並非座標,能夠看下下圖,方便理解
能夠發現top
、ascent
的值爲負數,descent
、bottom
的值爲正數,爲何會這樣呢?由於top
線和ascent線在基線的上方,FontMetrics
對象中的幾個成員變量的值都是表示相對基線的位置。
瞭解了FontMetrics
再結合下圖
能夠獲得下面的公式:
根據得出的公式能夠計算出基線的Y座標
top的Y座標 = 基線 + fontMetrics.top
基線 = top的Y座標 - fontMetrics.top
實現的代碼以下
Paint mPaint = new Paint();
mPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.sp18));
mPaint.setStrokeWidth(1);
mPaint.setColor(Color.RED);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float baseLine = cy-fontMetrics.top;//cy指定點的Y座標
canvas.drawText("wizardev", 0, baseLine, mPaint);
複製代碼
給定中間線寫文字,能夠說是自定義view寫文字時用的最多的了,如,將文字寫在圓的正中間,如上圖,圓的中心線將文字平分,這種就是本文說的給定中間線寫文字。文章前面說了,只要肯定了基線的位置,文字的位置也就肯定了,那麼像這種,怎樣來肯定基線的位置呢?這時咱們能夠藉助其餘的幾條線來計算出基線的位置。
如上圖,將top
和center
之間的間距設爲A
,將center
和baseline
之間的距離設爲B
,將center
和bottom
之間的距離設爲C
。這是就能夠得出下面的公式
A = C = (bottom - top)/2
B = baseline - center
B = C - (bottom - baseline )
而後根據上文獲得的公式:
bottom = fontMetrics.bottom + baseline
top = fontMetrics.top + baseline
能夠將最上面的公式修改成:
baseline - center = (fontMetrics.bottom + baseline - fontMetrics.top - baseline) / 2 - (fontMetrics.bottom + baseline - baseline)
最後的到的公式爲:
baseline = center - (fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom
上面的到的公式就是給出中心線的位置,最後計算出的基線所在位置的公式。
這種狀況應該是最簡單的了,直接把給定點的Y座標做爲基線的Y座標就好了。
文章到這裏,已經回答了文章開始的幾個問題,相信閱讀本文以後,你也對自定義View中畫文字有了更清晰的理解。若是仍有什麼疑問,能夠在文章下方留言。
本文已由公衆號「AndroidShared」首發