欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android自定义控件中获取文字宽高的方法已经drawText中的xy

程序员文章站 2022-05-23 15:22:05
...

宽度:

//1. 粗略计算文字宽度  
Log.d(TAG, "measureText=" + paint.measureText(str));    


//2. 计算文字所在矩形,可以得到宽高  
Rect rect = new Rect();  
paint.getTextBounds(str, 0, str.length(), rect);  
int w = rect.width();  
int h = rect.height();  
Log.d(TAG, "w=" +w+"  h="+h);  


drawText(Stringtext,float x, float y, Paint paint)

参数:

text 需要绘制的文字 
x 绘制文字原点X坐标 
y 绘制文字原点Y坐标 
paint 画笔

我们先来看一张图:

Android自定义控件中获取文字宽高的方法已经drawText中的xy

需要注意的是x,y并不是文字左上角的坐标点,它比较特殊,y所代表的是基线坐标y的坐标。

二、FontMetrics

Android自定义控件中获取文字宽高的方法已经drawText中的xy

从图中可以知道,除了基线,还有另外的四条线,它们分别是 topascentdescentbottom,它们的含义分别为:

  1. top:可绘制的最高高度所在线
  2. bottom:可绘制的最低高度所在线
  3. ascent :系统建议的,绘制单个字符时,字符应当的最高高度所在线
  4. descent:系统建议的,绘制单个字符时,字符应当的最低高度所在线

1、获取实例

Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();

Paint.FontMetricsInt fm=  mPaint.getFontMetricsInt();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

两个构造方法的区别是,得到对象的成员变量的值一个为float类型,一个为int类型。

2、成员变量

FontMetrics,它里面有如下五个成员变量:

        float ascent = fontMetrics.ascent;
        float descent = fontMetrics.descent;
        float top = fontMetrics.top;
        float bottom = fontMetrics.bottom;
        float leading = fontMetrics.leading;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

ascent,descent,top,bottom,leading 这些线的位置要怎么计算出来呢?我们先来看个图:

Android自定义控件中获取文字宽高的方法已经drawText中的xy

那么它们的计算方法如下:

ascent = ascent线的y坐标 - baseline线的y坐标;//负数

descent = descent线的y坐标 - baseline线的y坐标;//正数

top = top线的y坐标 - baseline线的y坐标;//负数

bottom = bottom线的y坐标 - baseline线的y坐标;//正数

leading = top线的y坐标 - ascent线的y坐标;//负数
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

FontMetrics的这几个变量的值都是以baseLine为基准的,对于ascent来说,baseline线在ascent线之下,所以必然baseliney值要大于ascent线的y值,所以ascent变量的值是负的。其他几个同理。

同样我们可以推算出:

ascent线Y坐标 = baseline线的y坐标 + fontMetric.ascent;

descent线Y坐标 = baseline线的y坐标 + fontMetric.descent;

top线Y坐标 = baseline线的y坐标 + fontMetric.top;

bottom线Y坐标 = baseline线的y坐标 + fontMetric.bottom
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3、绘制ascent,descent,top,bottom线

直接贴代码:

        int baseLineY = 200;

        mPaint.setTextSize(120);

        canvas.drawText("abcdefghijkl's", 200, baseLineY, mPaint);

        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();

        float top = fontMetrics.top + baseLineY;
        float ascent = fontMetrics.ascent + baseLineY;
        float descent = fontMetrics.descent + baseLineY;
        float bottom = fontMetrics.bottom + baseLineY;

        //绘制基线
        mPaint.setColor(Color.parseColor("#FF1493"));
        canvas.drawLine(0, baseLineY, getWidth(), baseLineY, mPaint);

        //绘制top直线
        mPaint.setColor(Color.parseColor("#FFB90F"));
        canvas.drawLine(0, top, getWidth(), top, mPaint);

        //绘制ascent直线
        mPaint.setColor(Color.parseColor("#b03060"));
        canvas.drawLine(0, ascent, getWidth(), ascent, mPaint);

        //绘制descent直线
        mPaint.setColor(Color.parseColor("#912cee"));
        canvas.drawLine(0, descent, getWidth(), descent, mPaint);

        //绘制bottom直线
        mPaint.setColor(Color.parseColor("#1E90FF"));
        canvas.drawLine(0, bottom, getWidth(), bottom, mPaint);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

在这段代码中,我们需要注意的是:canvas.drawText()中参数y是基线y的位置; mPaint.setTextAlign(Paint.Align.LEFT);指点(200,200)文字矩形的左边。然后计算各条直线的y坐标:

        float top = fontMetrics.top + baseLineY;
        float ascent = fontMetrics.ascent + baseLineY;
        float descent = fontMetrics.descent + baseLineY;
        float bottom = fontMetrics.bottom + baseLineY;
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

效果图:

Android自定义控件中获取文字宽高的方法已经drawText中的xy

4、绘制文字最小矩形、文字宽度、文字高度

(1)绘制文字最小矩形

drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)需要绘制矩形就需要知道矩形左上角坐标点,矩形长和宽。以上面例子为例:

left = 200 
top = ascent ; 
right= 200+矩形宽度; 
bottom = descent;

这样我们就可以绘制出最小矩形:

Android自定义控件中获取文字宽高的方法已经drawText中的xy

(2)文字高度

        float top = fontMetrics.top + baseLineY;
        float bottom = fontMetrics.bottom + baseLineY;
        //文字高度
        float height= bottom - top; //注意top为负数
        //文字中点y坐标
        float center = (bottom - top) / 2;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Android自定义控件中获取文字宽高的方法已经drawText中的xy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当然也可以: float height=Math.abs(top-bottom);

(3)文字宽度

 String text="abcdefghijkl's";
 //文字宽度
 float width = mPaint.measureText(text);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

本篇到这里就差不多结束了,源码比较简单,需要的留言。

已知中线,获取baseline(设置垂直居中)

我们一起来分析下原因,先来看一张分析图:

Android自定义控件中获取文字宽高的方法已经drawText中的xy

那么我们就可以得出:

baseline=centerY+B-fm.bottom;
  • 1
  • 1

如果以:

baseline=centerY + fontHeight / 2;
  • 1
  • 1

那么就会以bottom线作为文字的基线,这样就会造成文字位于中线之下。

结论

我们最终可知,当给定中间线center位置以后,那么baseline的位置为:


baseline = center + (FontMetrics.bottom - FontMetrics.top)/2 - FontMetrics.bottom;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

FontMetrics.bottom注意这里为正数。

所以最后计算为center - top/2 - bottom/2. 
水平居中:

paint.setTextAlign方法


此方法用来设置原点相对于文字内容范围(矩形)的位置。

参数

  • Paint.Align.LEFT:原点在文字内容的左边
  • Paint.Align.CENTER:原点在文字内容的中间
  • Paint.Align.RIGHT:原点在文字内容的右边
这里的居中表示文字在X坐标对应的位置
但是要设置在某条先上面画文字,或者在下面画文字,上面方法却会出问题;
参考:http://blog.csdn.net/harvic880925/article/details/50423762