Android:在画布上测量文本高度

Age*_*opf 8 android paint android-canvas

我目前正致力于渲染Bitmap,然后我想将其发送到移动打印机.但是,我正在努力测量文本的高度,所以我可以适当地提升y位置.

我的基本位图/画布/绘画配置是这样的(字体大小是16,位图的尺寸是200x400(宽x高)):

public MyRenderer() {
    // Initialize bitmap
    bitmap = Bitmap.createBitmap(200, 400, Bitmap.Config.ARGB_8888);

    // Initialize canvas
    canvas = new Canvas(bitmap);

    // Initialize brush (Paint instance)
    brush = new Paint();
    brush.setTextSize(16);
    brush.setTypeface(Typeface.SANS_SERIF);
    brush.setColor(Color.BLACK);
    brush.setStyle(Paint.Style.FILL);
    brush.setAntiAlias(true);
    brush.setTextAlign(Align.LEFT);
}
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都很好,现在我想做的是:如果我使用Paint的方法drawText,我需要提供x和y坐标.至于x为零(假设左对齐文本)但是对于y,我必须计算我打印的每个文本的高度并将其加起来,这样我就可以跟踪我当前的y位置.

这是奇怪的地方:我使用以下方法来确定文本的高度(使用我先前初始化的Paint对象 - 它被称为"brush"):

public int measureHeight(String text) {
    Rect result = new Rect();
    // Measure the text rectangle to get the height
    brush.getTextBounds(text, 0, text.length(), result);
    return result.height();
}
Run Code Online (Sandbox Code Playgroud)

上述方法为以下文本返回以下值:

  1. " Hello World "返回12的高度
  2. " 相机实例可用于计算3D变换并生成矩阵. "返回高度为16
  3. " Android设计简介:了解创建世界级Android用户界面的原则,构建模块和模式的地方.无论您是UI专业人士还是扮演该角色的开发人员,这些文档都会向您展示如何做出良好的设计决策,无论大小. "返回16的高度

对我来说有意义的是,数字2和3返回的高度高于数字1但是如果一条线的高度为12(正如数字1那样) - 没有意义,多条线的高度为16?

我在这里错过了什么吗?有一种方便的方法来测量文本的宽度(使用paint的实例和调用measureText("myText"),它完美地工作,但是当涉及到高度时,我很茫然,如上面给出的结果对我没有任何意义.

编辑

我知道,getTextBounds可能没有自动包装多行文本,没关系,我已经编写了一个分割文本的方法,但即使它只测量一行,上面给出的长度值似乎仍然不太可能.

dev*_*ole 16

我认为这是因为"计算"中的"p"延伸到基线以下,而"Hello World"仅包含高于基线的字母.

由于直线距离不应该依赖于你的文字,会发生什么具体的字母组成的你可能寻找Paint.FontMetrics可以通过获得Paint.getFontMetrics() .计算descent - ascent + leading以获得建议的基线距离(因为上升具有负值).

  • 更简单:[Paint.getFontSpacing()](http://developer.android.com/reference/android/graphics/Paint.html#getFontSpacing%28%29) (7认同)

Sur*_*gch 5

接受的答案中有一个小错误。如果您想要文字高度,则应使用

Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float textHeight = fm.descent - fm.ascent;
Run Code Online (Sandbox Code Playgroud)

如果您想要线高,则应使用

float lineHeight = fm.bottom - fm.top + fm.leading;
Run Code Online (Sandbox Code Playgroud)

行距是可选的行间距,因此,如果需要使行高,可以将其包括在内。但是,如果您只想要文本高度,则可以不使用它。

注意

  • 我从未见过leading任何东西比别的0,而据我可以告诉它甚至似乎在被忽略TextView的源代码(及其相关的LayoutStaticLayout等等)。如果我错了,请纠正我。因此,将它排除在高计算之外可能是安全的,但是我对此并不完全确定。

也可以看看