Android自定义控件中获取文字宽高的方法已经drawText中的xy
宽度:
//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
画笔
我们先来看一张图:
需要注意的是x,y
并不是文字左上角的坐标点,它比较特殊,y
所代表的是基线坐标y
的坐标。
二、FontMetrics
从图中可以知道,除了基线,还有另外的四条线,它们分别是 top
,ascent
,descent
和bottom
,它们的含义分别为:
- top:可绘制的最高高度所在线
- bottom:可绘制的最低高度所在线
- ascent :系统建议的,绘制单个字符时,字符应当的最高高度所在线
- 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
这些线的位置要怎么计算出来呢?我们先来看个图:
那么它们的计算方法如下:
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
线之下,所以必然baseline
的y
值要大于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
效果图:
4、绘制文字最小矩形、文字宽度、文字高度
(1)绘制文字最小矩形
由drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
需要绘制矩形就需要知道矩形左上角坐标点,矩形长和宽。以上面例子为例:
left = 200
top = ascent ;
right= 200+矩形宽度;
bottom = descent;
这样我们就可以绘制出最小矩形:
(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
- 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(设置垂直居中)
我们一起来分析下原因,先来看一张分析图:
那么我们就可以得出:
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
注意这里为正数。
paint.setTextAlign方法
此方法用来设置原点相对于文字内容范围(矩形)的位置。
参数
- Paint.Align.LEFT:原点在文字内容的左边
- Paint.Align.CENTER:原点在文字内容的中间
- Paint.Align.RIGHT:原点在文字内容的右边
下一篇: 泛型高级进阶二:泛型的高级使用