参考:https://blog.csdn.net/harvic880925/article/details/50423762
一、通过基线确定起点
void drawText(String text, float x, float y, Paint paint)
- 关键点:y的位置是文字的基线位置,而不是画其他图形的左上角
int baseLineX = 20 ;
int baseLineY = 200;
int baseLineY2 = 300;
//画基线
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);
canvas.drawLine(baseLineX, baseLineY2, 3000, baseLineY2, paint);
//写文字
paint.setColor(Color.BLACK);
paint.setTextSize(80); //以px为单位
canvas.drawText("A a B b C c D d E e F f G g", baseLineX, baseLineY, paint);
canvas.drawText("H h I i J j K k L l M m N n", baseLineX, baseLineY2, paint);
paint.setTextAlign(Paint.Align)
确定位置
- 关键点,这里的位置是说的起点x,y相对于文字的位置,而不是要绘制的文字对应起点x,y的位置,这个有点反人类。相对位置是根据所要绘制文字所在矩形来计算的
//画基线
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawLine(baseLineX, baseLineY, 2000, baseLineY, paint);
canvas.drawLine(baseLineX, baseLineY+100, 2000, baseLineY+100, paint);
canvas.drawLine(baseLineX, baseLineY+200, 2000, baseLineY+200, paint);
canvas.drawLine(x, 0, x, 2000, paint);
//写文字
paint.setColor(Color.DKGRAY);
paint.setTextSize(80); //以px为单位
paint.setTextAlign(Paint.Align.LEFT);//起点x,y在文字的左边
canvas.drawText("A a B b C c D d E e F f G g", x, baseLineY, paint);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText("A a B b C c D d E e F f G g", x, baseLineY+100, paint);
paint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText("A a B b C c D d E e F f G g", x, baseLineY+200, paint);
二、drawText的四线格与FontMetrics
-
top
: 可绘制的最高高度所在线 -
ascent
: 系统建议的,绘制单个字符时,字符应当的最高高度所在线 -
baseLine
:基线,字符底部对其的基准线 -
descent
:系统建议的,绘制单个字符时,字符应当的最低高度所在线 -
bottom
: 可绘制的最低高度所在线
baseLine
可以通过drawText(String text, float x, float y, Paint paint)
中的y来确定,那么其他四条线就需要用到FontMetrics
,其中最后一个leading
是指在文本行之间间隙
public static class FontMetrics {
public float top;
public float ascent;
public float descent;
public float bottom;
public float leading;
}
这四条线的高度计算:
- ascent = ascent线y坐标 - baseline线y坐标;
- descent = descent线y坐标 - baseline线y坐标;
- top = top线y坐标 - baseline线y坐标;
- bottom = bottom线y坐标 - baseline线y坐标;
但是由于FontMetrics
里面四个位置的值是相对于baseLine
计算的,所以要得到正真的对应值计算方法: - top线Y坐标 = baseline线的y坐标 + fontMetric.top;//fontMetric.top为负数
- ascent线Y坐标 = baseline线的y坐标 + fontMetric.ascent;//fontMetric.ascent为负数
- descent线Y坐标 = baseline线的y坐标 + fontMetric.descent;//fontMetric.descent为负数
- bottom线Y坐标 = baseline线的y坐标 + fontMetric.bottom;//fontMetric.bottom为正数
通过画笔获取FontMetrics
int baseLineY = 900;
int baseLineX = 0 ;
Paint paint = new Paint();
//写文字
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setTextSize(300); //以px为单位
paint.setStrokeWidth(3);
canvas.drawText("S C g j", baseLineX, baseLineY, paint);
//计算各线在位置
Paint.FontMetrics fm = paint.getFontMetrics();
float ascent = baseLineY + fm.ascent;
float descent = baseLineY + fm.descent;
float top = baseLineY + fm.top;
float bottom = baseLineY + fm.bottom;
//画top
paint.setColor(Color.RED);
canvas.drawLine(baseLineX, top, 2000, top, paint);
//画ascent
paint.setColor(Color.YELLOW);
canvas.drawLine(baseLineX, ascent, 2000, ascent, paint);
//画基线
paint.setColor(Color.GREEN);
canvas.drawLine(baseLineX, baseLineY, 2000, baseLineY, paint);
//画descent
paint.setColor(Color.CYAN);
canvas.drawLine(baseLineX, descent, 2000, descent, paint);
//画bottom
paint.setColor(Color.BLUE);
canvas.drawLine(baseLineX, bottom, 2000, bottom, paint);
三、所绘文字宽高和占用矩形区域获取
1.高度
int height = fontMetrics.bottom - fontMetrics.top;//所占高度
2.宽度
int width = paint.measureText(String text);
3.文字显示最小矩形
public void getTextBounds(String text, int start, int end, Rect bounds);
public void getTextBounds(char[] text, int index, int count, Rect bounds);
注意:这里获得的bounds
获取的y轴是以基线的相对位置的值,所以我们获取的bounds
顶部和底部需要加上基线的高度,才是准确位置
例如:
int baseLineY = 800;
int baseLineX = 0 ;
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setTextSize(300); //以px为单位
paint.setStrokeWidth(3);
String text = "S C g j";
canvas.drawText(text, baseLineX, baseLineY, paint);
//获取最小区域值,注意这里获取的是对应基线的比较高度,所以top和bottom需要加上基线高度
Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
int left = minRect.left;
int top = baseLineY+minRect.top;
int right = minRect.right;
int bottom = baseLineY+minRect.bottom;
paint.setColor(Color.GREEN);
canvas.drawLine(0,baseLineY,2000,baseLineY,paint);//基线
canvas.drawLine(left,0,left,2000,paint);//9
canvas.drawLine(0,top,2000,top,paint);//基线+( -221)
canvas.drawLine(right,0,right,2000,paint);//815
canvas.drawLine(0,bottom,2000,bottom,paint);//基线 +66
L.e(minRect.toShortString());// [9,-221][815,66]
paint.setColor(Color.RED);
canvas.drawRect(new RectF(left,top,right,bottom),paint);
4.文字占用空间矩形
int baseLineY = 800;
int baseLineX = 0 ;
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setTextSize(300); //以px为单位
paint.setStrokeWidth(3);
String text = "S C g j";
canvas.drawText(text, baseLineX, baseLineY, paint);
//获取最小区域值,注意这里获取的是对应基线的比较高度,所以top和bottom需要加上基线高度
Rect minRect = new Rect();
paint.getTextBounds(text,0,text.length(),minRect);
int left = minRect.left;
int top = baseLineY+minRect.top;
int right = minRect.right;
int bottom = baseLineY+minRect.bottom;
L.e(minRect.toShortString());// [9,-221][815,66]
paint.setColor(Color.RED);
canvas.drawRect(new RectF(left,top,right,bottom),paint);
//画text所占的区域
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int spaceTop = baseLineY + fm.top;
int spaceBottom = baseLineY + fm.bottom;
int width = (int)paint.measureText(text);
Rect rect = new Rect(baseLineX,spaceTop,baseLineX+width,spaceBottom);
paint.setColor(Color.GREEN);
canvas.drawRect(rect,paint);