android: Canvas drawText()文字居中


嫌麻煩可以直接看結論:

文本居中的公式:

float baseLineY = centerY + (Math.abs(fontMetrics.top) + Math.abs(fontMetrics.bottom)) /2 - fontMetrics.bottom

也可以簡化成:

float baselineY = centerY + (fontMetrics.bottom - fontMetrics.top)/2 - FontMetrics.bottom;

PS: 

1. centerY就是文本所在父View的中點的Y坐標。比如文本想要在一個高度為40dip的View中垂直居中,那centerY就是20dip; 
2.  FontMetrics.bottom  和   FontMetrics.top 是怎么拿到的?在繪制文本之前肯定先要給這段文本設置字體或大小這樣的代碼,比如:

mPaint.setTextSize();
在調用這段代碼之后就可以拿到  FontMetrics ,通過:

Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();

然后就可以通過上面的公式, 計算drawText()函數中傳入的Y值了。

-----------------------------------------------------------------------------------------  華麗麗的分割線 --------------------------------------------------------------------------------------------------------

這里面有個坑,就是drawText()方法里傳入的x, y坐標不是文字中心點的坐標, 而是基線的坐標!為什么是基線的坐標,是為了適配不同的文字,使不同文字放在一起時看起來更美觀協調,可以用下圖很直觀的解釋這種方式:

如何理解基線,可以參考下面這幅圖:

 

像圖上這樣安卓的文字繪制是相對於基線繪制的,也就是圖中的紅線,而top+bottom的長度就等於字體高度.即等於|top|+|bottom|絕對值

實際繪制的時候取決於基線上一個點來繪制文字,而這個點有三種分別對應為left,center,right如下圖:

而drawText()方法中x,y坐標所指的點就是上圖基線上三個點中的一個,具體是哪一個根據paint的setTextAlign()方法設置,默認為left

示例代碼如下

        Rect rect = new Rect(100,100,500,500);//畫一個矩形
        Paint rectPaint = new Paint();
        rectPaint.setColor(Color.BLUE);
        rectPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(rect, rectPaint);
 
        Paint textPaint = new Paint();
        textPaint.setColor(Color.WHITE);
        textPaint.setTextSize(50);
        textPaint.setStyle(Paint.Style.FILL);
        //該方法即為設置基線上那個點究竟是left,center,還是right  這里我設置為center
        textPaint.setTextAlign(Paint.Align.CENTER);
 
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        float top = fontMetrics.top;//為基線到字體上邊框的距離,即上圖中的top
        float bottom = fontMetrics.bottom;//為基線到字體下邊框的距離,即上圖中的bottom
 
        int baseLineY = (int) (rect.centerY() - top/2 - bottom/2);//基線中間點的y軸計算公式
 
        canvas.drawText("你好世界",rect.centerX(),baseLineY,textPaint);    

這里有點要注意textPaint.getFontMetrics()這個方法一定要在設置字體大小或者樣式等等一系列會影響字體的方法后在調用,不然獲取到的top和bottom值不准.

效果如下:

 

 

正好是在中間的,即證明等式是沒有問題的,再來分析這個等式是如何計算的

之所以drawText()方法中x,y指的是基線中間的那個點,是因為setTextAlign(Paint.Align.Center)

那么要想在正中間顯示文字,x只要為矩形的中點x坐標即可 x = rect.centerX()

要計算的就是基線中間圖上紅色點的y坐標了,看圖可以發現紅色點的y為矩形中點黑色點的y坐標+圖中黑色點和紅色點之間的距離

矩形y坐標為 rect.centerY()

黑色點和紅色點之間的距離為相對於基線的(top+bottom)/2 - bottom

而 top是相對於基線的所以為負數,所以公式為 (-top+bottom)/2 - bottom簡化下為-top/2 - bottom/2

所以最后計算為rect.centerY - top/2 - bottom/2 - bottom

計算方式就是用: 文本的總高度的一半減去基線到bottom線的距離,算出基線到中點之間的距離,然后再用中間的Y坐標加上這個距離,就是文本的基線位置。

 

 參考鏈接:

1. android canvas drawText()文字居中

2. 自定義控件之繪圖篇( 五):drawText()詳解

3. 迷之 paint.getTextBounds()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM