在使用getTextBouds的时候,demo绘制了一个大写的字母A,log打印了一下
Rect bounds = new Rect();
........
paint.getTextBounds(text,0,text.length(),bounds);
bounds.top = -318;
bounds.bottom = 0;
遂认为原点是文字TextBounds的左下角。
但事实却打脸了,犯了盲人摸象的错误,以偏概全。
Api中是这样说明的:
Return in bounds (allocated by the caller) the smallest rectangle that
encloses all of the characters, with an implied origin at (0,0).
然而并没有明确 implied origin 到底是哪个点。上面我认为原点是bounds的左下角,然而并不是,所以baseline的起点应该是唯一合理的原点了,下面来验证。
OK,我们再来看一下drawText方法
/**
* Draw the text, with origin at (x,y), using the specified paint. The
* origin is interpreted based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
paint.getNativeInstance(), paint.mNativeTypeface);
}
这里的y,是baseline对应的y轴坐标值。
所以,事实上,我们要计算出y轴的坐标值和外框Rect中点middle的y坐标之间的差值。
然后middle+差值,就是baseline应该的坐标。
minus = (bounds.top + bounds.bottom)/2;
注意,top在baseline上方,所以是负值,bottom在baseline下方(也有可能和baseline重合),所以是零或者正值。
minus计算出来是个负值,所以middle = middle - minus;
这样处理了一下,文字果然居中了。
so,上面的猜测是正确的,原点就是baseline的左边起点,问题搞定了。
核心细节有两个:
- drawText绘制文字时,y是baseline的y
- bounds的implied origin at (0,0).这个点是baseline的左边起点
来个图方便理解
drawText.png
网友评论
top在x轴(baseline)上方,是负值
bottom在x轴下方,是正值
so,你感受一下。。。