平時我們在自定義View經(jīng)常會遇到text的繪制非竿,經(jīng)常會需要文字水平居中,垂直居中谋竖,水平居中比較簡單红柱,而垂直居中稍微復雜,所以我們這里討論下垂直居中蓖乘。這里涉及到一個關鍵類Paint.FontMetrics锤悄,可以通過Paint實例的getFontMetrics()獲得,其中封裝幾個垂直相關的參數(shù)嘉抒。
- ascent:是baseline之上至字符最高處的距離
- descent:是baseline之下至字符最低處的距離
- top:指的是指的是最高字符到baseline的值零聚,即ascent的最大值
- bottom:指的是最下字符到baseline的值,即descent的最大值
當我們在設置paint.setTextSize(80)后些侍,打印日志:
06-24 02:56:54.792 7383-7383/sample.kingja.canvas E/FontMetricsView: top: -83.828125
06-24 02:56:54.792 7383-7383/sample.kingja.canvas E/FontMetricsView: ascent: -74.21875
06-24 02:56:54.792 7383-7383/sample.kingja.canvas E/FontMetricsView: descent: 19.53125
06-24 02:56:54.792 7383-7383/sample.kingja.canvas E/FontMetricsView: bottom: 21.679688
我們發(fā)現(xiàn)4個參數(shù)有有正數(shù)握牧,有負數(shù),根據(jù)上面的說明后娩梨,現(xiàn)在我們可以確定baseline在里面充當了一個基準線沿腰,也就是0位置。于是我們先用以下坐標點作為一個baseline的坐標繪制一段文字狈定。measuredWidth颂龙,measuredHeight 為控件的寬习蓬,高。
baseX = measuredWidth * 0.5f - textWidth * 0.5f;//textWidth = paint.measureText(text)
baseY = measuredHeight * 0.5f;
為了直觀措嵌,我們用直線實體化了這幾個參數(shù)躲叼,效果如下:
我們發(fā)現(xiàn)文字已經(jīng)完成了水平居中,這樣只要將font middle這條白線降到控件的中間黑線就可以實現(xiàn)垂直居中了企巢,那么只要求出偏移量offsetY就可以了枫慷,很明顯,font middle到base的距離=文字高度/2-bottom到base的距離
float offsetY=0.5f*fontHeight-bottom;
baseY+=offsetY;
按照新的baseline坐標浪规,我們畫出的文字效果圖如下:
基本完成了需求或听,但是由于這個時候我們fontHeight = bottom - top,感覺效果并不是很理想笋婿,因為ascent以上到top挺多空隙誉裆,而descent到bottom的空隙并不大,這會讓人感覺到文字略微偏下缸濒,但是Android既然設置了top和bottom足丢,那么文字的高度范圍可以被認為在bottom和top之間。所以大家如果想要更理想的效果可把fontHeight設為descent-ascent庇配。我個人覺得斩跌,fontHeight = bottom - top這樣更穩(wěn)妥點。當然我也做出了效果捞慌,大家可以對比下:
看得出滔驶,雖然差別不多,但是還是有所出入卿闹,比如“好”字那個子的橫筆畫,一個在中線下萝快,一個在中線上锻霎。
最后給出兩種計算方式的公式:
- 以fontHeight = bottom - top為文字高度
baseY = measuredHeight * 0.5f+(bottom - top)*0.5f-bottom;
- 以fontHeight = descent- ascent為文字高度
baseY = measuredHeight * 0.5f+(descent-ascent)*0.5f-descent;
我想,到現(xiàn)在揪漩,大家應該比較確定旋恼,這是靠譜的垂直居中了吧。