自定義View的文字居中處理
自定義View中想要實現文字的居中處理,首先要了解文字繪製的基準和文字的邊界

image.png
如圖所示圓圈在螢幕中心,而文字在圓的中心。當我們直接呼叫drawText
canvas.drawText(text,getWidth()/2,getHeight()/2,mPaint);

image.png
你會發現文字是偏上的,為什麼會這樣呢?這是因為 文字繪製的是以文字的基線(baseline)為基準點進行繪製的 ,而文字基線大概如下圖所示,所以你看到的就是向上偏移的文字,要想居中只要y軸減去文字高度的一半就可以實現。

image.png
獲得文字高度的方法
- 使用
getTextBounds(String text, int start, int end, Rect bounds)
text是想要測量的文字,start和end是測量的起點和終點,在設定了文字的大小時候,使用
getTextBounds
傳入Rect就可以獲得一個剛好包圍所有文字的矩形Rect, 注意這個Rect的座標是以文字baseline為x軸的相對位移,rect.top是一個負值,rect.bottom是一個正直 ,而不是一個絕對座標,當文字的頂點和底部不斷變化時,這個矩形的範圍也會不斷變化獲得Rect
mPaint.setTextSize(125); mPaint.getTextBounds(text, 0, text.length(), mTextRect);
所以這時你可以這樣繪製位置,這樣繪製出來的可以說是在文字的真正的居中的了,但是使用 getTextBounds
計算文字有一個問題,就是 當你的文字有動畫或者變動時,由於不同的文字邊界不一樣,你會看到上下變動的文字,所以 getTextBounds
一般用在靜態的文字中
canvas.drawText(text, halfWidth, halfHeight - (mTextRect.top + mTextRect.bottom) / 2, mPaint);
- 使用
getFontMetrics()
使用這個方法可以獲得文字的4個位置
ascent、descent、top、bottom
的值,這幾個值的代表的位置如下圖所示,image.png
-
ascent
是圖中綠色的線,代表的是系統推薦的在baseline之上的文字間距值,descent
和ascent
是對應的,如圖橙色的線所示,它表示的是系統推薦的在baseline之下的文字間距的值, 這兩個值是所有普通字元的頂點和底部,普通字元高不會超過ascent
,低不會低於descent
,ascent 和 descent 這兩個值還可以通過 Paint.ascent() 和 Paint.descent() 來快捷獲取。 -
top
和bottom
如圖藍色和紅色線所示,top
和bottom
限制的是所有字形的頂部和底部 ,有些特殊字元會超過descent
和ascent
,但是不會超過top
和bottom
的限制,這兩個值也是相對於baseline的偏移。
這時你可以這樣處理文字的偏移
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics(); canvas.drawText(text, halfWidth, halfHeight - (fontMetrics.ascent + fontMetrics.descent) / 2, mPaint);
或者
canvas.drawText(text, halfWidth, halfHeight - (fontMetrics.top + fontMetrics.bottom) / 2, mPaint);
相對於 getTextBounds
,這樣處理的文字是不會存在抖動現象的, 通常在動態文字時都會使用這種方式來居中
總結
用以上兩種方式都可以實現文字的居中處理,當我們知道其中的原理後,用起來就會得心應手不用每次都要去網上搜索