原文地址:http://blog.51cto.com/mikewang/871765
最近的一個模塊正好用到字體的相關內容,整理出來。
(一) 字體的幾個參數 ,以Android API文檔定義爲準,見下圖
要點如下:
1. 基準點是baseline
2. Ascent是baseline之上至字符最高處的距離
3. Descent是baseline之下至字符最低處的距離
4. Leading文檔說的很含糊,其實是上一行字符的descent到下一行的ascent之間的距離
5. Top指的是指的是最高字符到baseline的值,即ascent的最大值
6. 同上,bottom指的是最下字符到baseline的值,即descent的最大值
Note:網上有很多錯誤的圖,如果有疑問,就參看文檔,區分對錯。
爲了幫助理解,我特此搜索了不同的示意圖。對照示意圖,會很容易理解FontMetrics的參數。
pic-1
pic-2
pic-3
pic-4
pic-5
pic-6
(二) 測試
1,測試的代碼直接使用網上的代碼,因爲重複着衆多,無所給出原始出處,故不注出。
我增加了Bitmap作爲輸出顯示,完整代碼如下:
- public class FontMetricsDemoActivity extends Activity {
- private Canvas canvas;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- Paint textPaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- textPaint.setTextSize( 55);
- textPaint.setColor( Color.WHITE);
- // FontMetrics對象
- FontMetrics fontMetrics = textPaint.getFontMetrics();
- String text = "abcdefghijklmnopqrstu";
- // 計算每一個座標
- float baseX = 0;
- float baseY = 100;
- float topY = baseY + fontMetrics.top;
- float ascentY = baseY + fontMetrics.ascent;
- float descentY = baseY + fontMetrics.descent;
- float bottomY = baseY + fontMetrics.bottom;
- float leading = baseY + fontMetrics.leading;
- Log.d("fontMetrics", "baseX is:" + 0);
- Log.d("fontMetrics", "baseY is:" + 100);
- Log.d("fontMetrics", "topY is:" + topY);
- Log.d("fontMetrics", "ascentY is:" + ascentY);
- Log.d("fontMetrics", "descentY is:" + descentY);
- Log.d("fontMetrics", "bottomY is:" + bottomY);
- Log.d("fontMetrics", "leading is:" + leading);
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fontmetrics);
- Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
- canvas = new Canvas(mutableBitmap);
- // 繪製文本
- canvas.drawText(text, baseX, baseY, textPaint);
- // BaseLine描畫
- Paint baseLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- baseLinePaint.setColor( Color.RED);
- canvas.drawLine(0, baseY, canvas.getWidth(), baseY, baseLinePaint);
- // Base描畫
- canvas.drawCircle( baseX, baseY, 5, baseLinePaint);
- // TopLine描畫
- Paint topLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- topLinePaint.setColor( Color.LTGRAY);
- canvas.drawLine(0, topY, canvas.getWidth(), topY, topLinePaint);
- // AscentLine描畫
- Paint ascentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- ascentLinePaint.setColor( Color.GREEN);
- canvas.drawLine(0, ascentY, canvas.getWidth(), ascentY, ascentLinePaint);
- // DescentLine描畫
- Paint descentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- descentLinePaint.setColor( Color.YELLOW);
- canvas.drawLine(0, descentY, canvas.getWidth(), descentY, descentLinePaint);
- // ButtomLine描畫
- Paint bottomLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- bottomLinePaint.setColor( Color.MAGENTA);
- canvas.drawLine(0, bottomY, canvas.getWidth(), bottomY, bottomLinePaint);
- ImageView imageView = (ImageView) findViewById(R.id.imageView1);
- imageView.setImageBitmap(mutableBitmap);
- }
- }
log顯示如下:
Note1:注意到各個數值都是整數,這是建立在baseY=100的情況下,去掉baseY,重新運行代碼,log如下:
Note2: 參照線爲baseline,即baseline=0的情況下,其他各線的數值。leading = 0,即行間距=0
2,以上是根據paint設置,獲取相關的FontMetrics屬性,並且只繪製了一行字符串,我們猜想,如果是多行,是否可以獲得行間距leanding,代碼如下:
- //test_multiply_lines
- TextView textView = (TextView) findViewById(R.id.textView1);
- String textMultiLines = "abcdefghijklmnopqrstuabcdefghijklmnopqrstuabcdefghijklmnopqrstuabcdefghijklmnopqrstuabcdefghijklmnopqrstu";
- textView.setTextSize(55);
- textView.setText(textMultiLines);
- FontMetrics fontMetrics2 = textView.getPaint().getFontMetrics();
- // 計算每一個座標
- float topY = fontMetrics2.top;
- float ascentY = fontMetrics2.ascent;
- float descentY = fontMetrics2.descent;
- float bottomY = fontMetrics2.bottom;
- float leading = fontMetrics2.leading;
- Log.d("fontMetrics", "topY is:" + topY);
- Log.d("fontMetrics", "ascentY is:" + ascentY);
- Log.d("fontMetrics", "descentY is:" + descentY);
- Log.d("fontMetrics", "bottomY is:" + bottomY);
- Log.d("fontMetrics", "leading is:" + leading);
log如下:
Note:顯然,即使是多行的情況下,仍不能獲得leading。
3,如果text是單行,獲得各個屬性將會怎樣,代碼如下:
- String text = "abcdefghijklmnopqrstu";
- TextView textView = (TextView) findViewById(R.id.textView1);
- textView.setTextSize(55);
- textView.setText(text);
- FontMetrics fontMetrics = textView.getPaint().getFontMetrics();
- // 計算每一個座標
- float baseX = 0;
- float baseY = 100;
- float topY = baseY + fontMetrics.top;
- float ascentY = baseY + fontMetrics.ascent;
- float descentY = baseY + fontMetrics.descent;
- float bottomY = baseY + fontMetrics.bottom;
- float leading = fontMetrics.leading;
- Log.d("fontMetrics", "topY is:" + fontMetrics.top);
- Log.d("fontMetrics", "ascentY is:" + fontMetrics.ascent);
- Log.d("fontMetrics", "descentY is:" + fontMetrics.descent);
- Log.d("fontMetrics", "bottomY is:" + fontMetrics.bottom);
- Log.d("fontMetrics", "leading is:" + fontMetrics.leading);
log如下圖所示:
Note:與多行獲得的屬性都相同。
結論:
A:雖然paint和textView所設置的textSize均爲55,且爲相同的字符串,但是兩個獲得的FontMetrics屬性值並不相同。但是,我們發現,做除法之後,均爲1.5倍關係。做出猜測,即Paint下,爲mdpi對應的size,而TextView的size已經關聯到了顯示屏幕本身的320dip。所以獲得屬性值均爲整1.5倍數
B:各種情況下,均未獲得leading值。