Android字体属性Paint.FontMetrics

(一) 字体的几个参数 ,以Android API文档定义为准,见下图

Android字体属性Paint.FontMetrics_第1张图片

要点如下:

1. 基准点是baseline

2. Ascent是baseline之上至字符最高处的距离

3. Descent是baseline之下至字符最低处的距离

4. Leading文档说的很含糊,这个我还不清楚,但有人说是上一行字符的descent到下一行的ascent之间的距离,也有人说不是

5. Top指的是指的是最高字符到baseline的值,即ascent的最大值

6. 同上,bottom指的是最下字符到baseline的值,即descent的最大值


(二)贴几张图看看:

pic_1


pic_2

Android字体属性Paint.FontMetrics_第2张图片

pic_3

字体为斜体状态下(你没有看错,中文只设置mPaint.setTypeface(Typeface.create("", Typeface.ITALIC))是斜体不了的):

Android字体属性Paint.FontMetrics_第3张图片


pic-4


上验证代码:

public class MyView extends View {


	private Paint mPaint = new Paint();

	public MyView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	
	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public MyView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		mPaint.reset();
		mPaint.setColor(Color.WHITE);
		mPaint.setTextSize(80);
		//设置字体为斜体
		mPaint.setTypeface(Typeface.create("", Typeface.ITALIC));
		// FontMetrics对象
		FontMetrics fontMetrics = mPaint.getFontMetrics();
		String text = "中国话fgiqÃÇŸŒú";
		// 计算每一个坐标
		float textWidth = mPaint.measureText(text);
		float baseX = 30;
		float baseY = 700;
		float topY = baseY + fontMetrics.top;
		float ascentY = baseY + fontMetrics.ascent;
		float descentY = baseY + fontMetrics.descent;
		float bottomY = baseY + fontMetrics.bottom;
		// 绘制文本
		canvas.drawText(text, baseX, baseY, mPaint);
		// BaseLine描画
		mPaint.setColor(Color.RED);
		canvas.drawLine(baseX, baseY, baseX + textWidth, baseY, mPaint);
		mPaint.setTextSize(20);
		canvas.drawText("base", baseX + textWidth, baseY, mPaint);
		// Base描画
		canvas.drawCircle(baseX, baseY, 5, mPaint);
		// TopLine描画
		mPaint.setColor(Color.LTGRAY);
		canvas.drawLine(baseX, topY, baseX + textWidth, topY, mPaint);
		canvas.drawText("top", baseX + textWidth, topY, mPaint);
		// AscentLine描画
		mPaint.setColor(Color.GREEN);
		canvas.drawLine(baseX, ascentY, baseX + textWidth, ascentY, mPaint);
		canvas.drawText("ascent", baseX + textWidth, ascentY + 10, mPaint);
		// DescentLine描画
		mPaint.setColor(Color.YELLOW);
		canvas.drawLine(baseX, descentY, baseX + textWidth, descentY, mPaint);
		canvas.drawText("descent", baseX + textWidth, descentY, mPaint);
		// ButtomLine描画
		mPaint.setColor(Color.MAGENTA);
		canvas.drawLine(baseX, bottomY, baseX + textWidth, bottomY, mPaint);
		canvas.drawText("buttom", baseX + textWidth, bottomY + 10, mPaint);
		super.onDraw(canvas);
	}
}

(三)将字画在矩形背景的正中位置

FontMetrics.top的数值是个负数,其绝对值就是字体绘制边界到baseline的距离。
所以如果是把文字画在 FontMetrics高度的矩形中, drawText就应该传入 -FontMetrics.top。
要画在targetRect的居中位置,baseline的计算公式就是(本人抄的原博主的,也不知道怎么计算的):

targetRect.top + (targetRect.bottom - targetRect.top) / 2 - (FontMetrics.bottom - FontMetrics.top) / 2 - FontMetrics.top

代码应该改成(顺便加入水平居中):

[java]  view plain copy
  1. @Override  
  2. public void onDraw (Canvas canvas) {  
  3.     Rect targetRect = new Rect(50501000200);  
  4.     Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  5.     paint.setStrokeWidth(3);  
  6.     paint.setTextSize(80);  
  7.     String testString = "测试:ijkJQKA:1234";  
  8.     paint.setColor(Color.CYAN);  
  9.     canvas.drawRect(targetRect, paint);  
  10.     paint.setColor(Color.RED);  
  11.     FontMetricsInt fontMetrics = paint.getFontMetricsInt();  
  12.         // 转载请注明出处:http://blog.csdn.net/hursing  
  13.     int baseline = targetRect.top + (targetRect.bottom - targetRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;  
  14.     // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()  
  15.     paint.setTextAlign(Paint.Align.CENTER);  
  16.     canvas.drawText(testString, targetRect.centerX(), baseline, paint);  
  17. }  
效果:



(四)注意:

A:一个字符f得到的测试结果与上边的代码得到的fontmetrics值相同。

B:如果pain设置的textSize均为55,或者textView设置字体大小为55,且为相同的字符串,但是两个获得的FontMetrics属性值并不相同。但是,我们发现,做除法之后,均为1.5倍关系。做出猜测,即Paint下,为mdpi对应的size,而TextView的size已经关联到了显示屏幕本身的320dip。所以获得属性值均为整1.5倍数

C:各种情况下,均未获得leading值。

D:好似还可以直接让CPU来渲染字体,出门右转http://blog.jobbole.com/70468/点击打开链接 


参考:http://blog.csdn.net/hursing/article/details/18703599

参考:http://blog.jobbole.com/70468/

你可能感兴趣的:(Android应用)