关于Canvas.drawText中xy位置问题

本文详细解析了Android中Canvas绘制文本的原理与实践技巧,重点介绍了如何利用FontMetrics精确控制文本的位置,并提供了调整文本垂直居中的实用方法。

问:canvas.drawText("3", x, y, paint);  x和y是指画得时候数字3中心的坐标吗?还是左上角的坐标?
答:x默认是‘3’这个字符的左边在屏幕的位置,如果设置了paint.setTextAlign(Paint.Align.CENTER);那就是字符的中心,y是指定这个字符baseline在屏幕上的位置。

public void drawText (String text, float x, float y, Paint paint)
Since: API Level 1 Draw the text, with origin at (x,y), using the specified paint.
The origin is interpreted based on the Align setting in the paint.
Parameters
text The text to be drawn
x The x-coordinate of the origin of the text being drawn
y The y-coordinate of the origin of the text being drawn
paint The paint used for the text (e.g. color, size, style)

Canvas 作为绘制文本时,使用FontMetrics对象,计算位置的坐标。 它的思路和java.awt.FontMetrics的基本相同。 
FontMetrics对象它以四个基本坐标为基准,分别为:

FontMetrics.top
FontMetrics.ascent
FontMetrics.descent
FontMetrics.bottom

 

  1.    Paint textPaint = new Paint( Paint.ANTI_ALIAS_FLAG);  
  2.    textPaint.setTextSize( 35);  
  3.    textPaint.setColor( Color.WHITE);  
  4.   
  5.    // FontMetrics对象  
  6.    FontMetrics fontMetrics = textPaint.getFontMetrics();  
  7.    String text = "abcdefghijklmnopqrstu";  
  8.   
  9.    // 计算每一个坐标  
  10.    float baseX = 0;  
  11.    float baseY = 100;  
  12.    float topY = baseY + fontMetrics.top;  
  13.    float ascentY = baseY + fontMetrics.ascent;  
  14.    float descentY = baseY + fontMetrics.descent;  
  15.    float bottomY = baseY + fontMetrics.bottom;  
  16.   
  17.    // 绘制文本  
  18.    canvas.drawText( text, baseX, baseY, textPaint);  
  19.   
  20.    // BaseLine描画  
  21.    Paint baseLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);>  
  22.    baseLinePaint.setColor( Color.RED);  
  23.    canvas.drawLine(0, baseY, getWidth(), baseY, baseLinePaint);  
  24.   
  25.    // Base描画  
  26.    canvas.drawCircle( baseX, baseY, 5, baseLinePaint);  
  27.   
  28.    // TopLine描画  
  29.    Paint topLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);  
  30.    topLinePaint.setColor( Color.LTGRAY);  
  31.    canvas.drawLine(0, topY, getWidth(), topY, topLinePaint);  
  32.   
  33.    // AscentLine描画  
  34.    Paint ascentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);  
  35.    ascentLinePaint.setColor( Color.GREEN);  
  36.    canvas.drawLine(0, ascentY, getWidth(), ascentY, ascentLinePaint);  
  37.   
  38.    // DescentLine描画  
  39.    Paint descentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);  
  40.    descentLinePaint.setColor( Color.YELLOW);  
  41.    canvas.drawLine(0, descentY, getWidth(), descentY, descentLinePaint);  
  42.   
  43.    // ButtomLine描画  
  44.    Paint bottomLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);  
  45.    bottomLinePaint.setColor( Color.MAGENTA);  
  46.    canvas.drawLine(0, bottomY, getWidth(), bottomY, bottomLinePaint);  

 

drawText画字符串是baseline对齐的。所以要特别注意这点,不然画文字可能画到其它地方而误以为没有画出来。

如果baseline对齐的话:底端的Y坐标是:(行高-字体高度)/2+字体高度 ,但是字符串并不居中,经过测试如果:(行高-字体高度)/2+字体高度-6 ,就稍微居中了一点。 以上的方法只是一个取巧的做法,网上也没有找到设置文字居中的方法。

按上面办法会有误差。加上那段距离应该就行了:

  1. FontMetrics fontMetrics = mPaint.getFontMetrics();  
  2. float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;  
  3. float offY = fontTotalHeight / 2 - fontMetrics.bottom;  
  4. float newY = baseY + offY;  
  5. canvas.drawText(text, baseX, newY, paint); 
`Canvas.drawText()` 是 Android 中用于在画布上绘制文本的核心 API。它有多个重载方法,允许开发者灵活地绘制字符串内容。 ### 常用 `drawText()` 方法签名: ```java public void drawText(String text, float x, float y, Paint paint) public void drawText(String text, int start, int end, float x, float y, Paint paint) public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) public void drawText(char[] text, int index, int count, float x, float y, Paint paint) ``` ### 参数说明: - `text`:要绘制的文本内容。 - `x`, `y`:文本绘制的起始坐标(**注意:y 是基线 baseline 的位置,不是顶部对齐**)。 - `paint`:绘制文本时使用的画笔对象,控制颜色、字体大小、样式等。 - `start` / `end` / `index` / `count`:用于指定绘制文本的一部分。 ### 示例代码: ```java public class MyTextView extends View { private Paint mPaint; private String mText = "Hello Canvas"; public MyTextView(Context context) { super(context); init(); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mPaint = new Paint(); mPaint.setColor(Color.RED); mPaint.setTextSize(48); mPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawText(mText, 100, 100, mPaint); } } ``` ### 注意事项: - `y` 坐标是**基线(baseline)**的位置,不是文字的顶部或底部。 - 可使用 `Paint.setTextSize()` 设置字体大小。 - 可通过 `Paint.setTextAlign()` 设置文本对齐方式(LEFT、CENTER、RIGHT)。 - 使用 `StaticLayout` 或 `Canvas.translate()` 可实现多行文本绘制。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值