参考自:https://blog.csdn.net/hursing/article/details/18703599
看博客的时候,有看到canvas.drawText()方法,但关于baseline这个点看了好久,也看不懂,于是乎,自己写了个demo,总算搞明白了
如若我们要在一个矩形内,绘制文本,需要文字竖直居中
/**
* text 要绘制的文字
* x 文字左端x坐标
* y 文字基线baseline的y值
* paint 画笔
*/
drawText(String text, float x, float y, @NonNull Paint paint)
文字左端的x坐标不用解释,但文字基线baseline的y值是什么呢?
管它是什么,画出来再猜
Rect rect = new Rect(50, 50, 1000, 200);
mPaint.setColor(Color.CYAN);
canvas.drawRect(rect, mPaint);
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, mContext.getResources().getDisplayMetrics()));
mPaint.setColor(Color.BLACK);
canvas.drawText(str, rect.left, rect.bottom, mPaint);
如上图,即为矩形的底边为baseline的效果,其实类似于英文四线作业本的第三根线
那么,我们想把文字居中就要很准确的计算出baseline的y坐标
计算之前我们要再来认识另一个类,FontMetrics
还是先画为敬
int x = 50;
int y = 200;
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.BLACK);
canvas.drawText(str, x, y, mPaint);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//绘制baseline
mPaint.setColor(Color.RED);
canvas.drawLine(50, 200, 1000, 200, mPaint);
canvas.translate(x, y);
//画fontMetrics.top位置
mPaint.setColor(Color.YELLOW);
canvas.drawLine(0, fontMetrics.top, 1000, fontMetrics.top, mPaint);
//画fontMetrics.bottom位置
mPaint.setColor(Color.MAGENTA);
canvas.drawLine(0, fontMetrics.bottom, 1000, fontMetrics.bottom, mPaint);
看下效果吧:
可以看到,黄线为fontmetrics.top,紫线为fontmetrics.bottom,文字在二者其中并且居中
顺便打印出fontmetrics.top fontmetrics.bottom的值如下:
*******************fontMetrics.top******************-76.04297
*******************fontMetrics.bottom******************19.511719
看到fontMetrics.top的值为负数
FontMetrics是描述给定文本字体的各种属性的类,我自己总结的就是包含了字体可绘制边界
fontmetrics.top 给定字体大小的文本高于基准线的最大距离
同样的,fontmetrics.bottom 给定字体大小的文本低于基准线的最大距离
其实,根据上图已经可以看的很清楚了,我解释的可能也不够准确,已经很努力的用我的四级解释了
重点是基线baseline的y坐标为0,我意识到这点的时候,才把博主的博客看懂
回到原来的问题,我们要在给定矩形内绘制文字
baseline = rect.centerY() - (fontmetrics.bottom - fontmetrics.top)/2 - fontmetrics.top
baseline = 矩形的数值方向中心线y值 - 字体可绘制边界竖直方向的一半 + 字体可绘制边界的竖直方向顶部到基线的距离即fontmetrics.top
参照下图更好理解:
Rect rect = new Rect(50, 50, 1000, 200);
mPaint.setColor(Color.CYAN);
canvas.drawRect(rect, mPaint);
mPaint.setColor(Color.BLACK);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float bottomLineY = rect.centerY() - (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.top;
canvas.drawText(str, rect.left, bottomLineY, mPaint);
效果:居中,RNG冠军,nice!
另外,区分下,FontMetrics 和 getTextBounds 的区别
int x = 50;
int y = 200;
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.BLACK);
canvas.drawText(str, x, y, mPaint);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
Log.d("test", "*******************fontMetrics.top******************" + fontMetrics.top);
Log.d("test", "*******************fontMetrics.bottom******************" + fontMetrics.bottom);
//绘制baseline
mPaint.setColor(Color.RED);
canvas.drawLine(50, 200, 1000, 200, mPaint);
canvas.translate(x, y);
//画fontMetrics.top位置
mPaint.setColor(Color.YELLOW);
canvas.drawLine(0, fontMetrics.top, 1000, fontMetrics.top, mPaint);
//画fontMetrics.bottom位置
mPaint.setColor(Color.MAGENTA);
canvas.drawLine(0, fontMetrics.bottom, 1000, fontMetrics.bottom, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(2);
//绘制汉字的字体的字体范围
Rect bounds1 = new Rect();
mPaint.setColor(Color.GREEN);
mPaint.getTextBounds(str, 0, 3, bounds1);
canvas.drawRect(bounds1, mPaint);
//绘制包含英文字体的字体范围
Rect bounds2 = new Rect();
mPaint.setColor(Color.BLUE);
mPaint.getTextBounds(str, 0, 7, bounds2);
canvas.drawRect(bounds2, mPaint);
//通过以上两个矩形对比可知,汉字的文字边框和英文的文字边框不同
老规矩,看图说话
我的总结是:
getTextBounds为当前文字实际绘制的最小矩形
FontMetrics为给定大小的文字可绘制边界(区分实际绘制,其实我也不是特别清楚,我觉得可能是因为存在下图的文字,所以可绘制边界要预留其额外的距离)
最近越来越觉得,自己要学的东西很多,要得到自己想要的,就要付出足够的努力,以前看别人博客经常会一言不合就被鸡汤,自己也炖一勺尝尝。。。加油吧!