Android: 绘制的文本如何排版
项目需求,在一个特定的矩形内绘制一段文本,并且要让文本处于矩形的正中间。
原来的方法:
先设置paint颜色,字体,字体大小等等
paint.setColor(Color.WHITE);
paint.setTextSize(fontSize);
Path textPath = new Path();
textPath.moveTo(rect_x1,textPontY);
textPath.cubicTo(rect_x1,textPontY, rect_x1,textPontY, rect_x1+rect_width,textPontY);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawTextOnPath(mailBox.getBoxNumber(), textPath, 0, 0, paint);
关键在于这个 textPontY 的值如何确定。如果定位不准,达到的效果就是在水平方向上它是居中的(3点一线),在垂直方向并不是
后来想到,通过path来设置,让path沿着一个封闭的矩形,如下:
Path textPath = new Path();
textPath.moveTo(rect_x1,rect_y1);
textPath.lineTo(rect_x1 + rect_width, rect_y1);
textPath.lineTo(rect_x1 + rect_width, rect_y1+rect_height);
textPath.lineTo(rect_x1 , rect_y1+rect_height);
textPath.lineTo(rect_x1,rect_y1);
textPath.close();
然后 设置 paint.setTextAlign(Paint.Align.CENTER); ,然后再 canvas.drawTextOnPath(mailBox.getBoxNumber(), textPath, 0, 0, paint);
结果证明这个想法是错误的,它并不能智能定位到 矩形正中间的位置。
如何 textPontY 的值如何确定 ?涉及到 “android 字体大小对应的高度”
下文来自: http://www.iteye.com/topic/474526
Canvas 作为绘制文本时,使用FontMetrics对象,计算位置的坐标。
它的思路和java.awt.FontMetrics的基本相同。
FontMetrics对象
它以四个基本坐标为基准,分别为:
・FontMetrics.top
・FontMetrics.ascent
・FontMetrics.descent
・FontMetrics.bottom
该图片将如下
- Paint textPaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- textPaint.setTextSize( 35);
- 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;
- // 绘制文本
- canvas.drawText( text, baseX, baseY, textPaint);
- // BaseLine描画
- Paint baseLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);>
- baseLinePaint.setColor( Color.RED);
- canvas.drawLine(0, baseY, 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, getWidth(), topY, topLinePaint);
- // AscentLine描画
- Paint ascentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- ascentLinePaint.setColor( Color.GREEN);
- canvas.drawLine(0, ascentY, getWidth(), ascentY, ascentLinePaint);
- // DescentLine描画
- Paint descentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- descentLinePaint.setColor( Color.YELLOW);
- canvas.drawLine(0, descentY, getWidth(), descentY, descentLinePaint);
- // ButtomLine描画
- Paint bottomLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- bottomLinePaint.setColor( Color.MAGENTA);
- canvas.drawLine(0, bottomY, getWidth(), bottomY, bottomLinePaint);
由上可得出一个常识:drawText 绘制文本时,是从 baseLine这个位置开始的,并不简单认为是从 文本的左下角开始绘制。
由上图可以分析出:
float textPontY = rect_y1 + (rect_height - temp)/2.0f + temp - fontMetrics.bottom;
把 textPointY设置成这样的值,就对了!