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

发布于 2025-01-07 08:20:45 字数 1648 浏览 0 评论 0原文

我目前正在渲染位图,然后我想将其发送到移动打印机。然而,我正在努力测量文本的高度,因此我可以适当地推进 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);
}

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

这就是奇怪的地方:我使用以下方法来确定文本的高度(使用我之前初始化的 Paint 对象 - 它称为“画笔”):

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();
}

上面的方法返回以下文本的值:

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

这是有道理的 ,数字 2 和 3 返回的高度比数字 1 更高,但如果一条线的高度为 12(如数字 1 所示),那么多条线的高度为 16 是没有意义的吗?

对我来说 有一种方便的方法来测量宽度文本的(使用paint实例并调用measureText(“myText”),它工作得很好,但是当谈到高度时,我很茫然,因为上面给出的结果对我来说没有任何意义。

编辑

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

I am currently working on rendering a Bitmap, that I then want to send to a mobile printer. However, I am struggling with measuring the height of my text, so I can advance the y position appropriately.

My basic bitmap/canvas/paint configuration is this (Font Size is 16 and the dimensions of the bitmap are 200x400 (width x height):

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);
}

So far so good, now what I want to do is: If I use the Paint's method drawText I need to supply the x and y coordinates. As for x that's zero (assuming left aligned text) but as for y, I'd have to calculate the height of each text I print and add it up, so I can keep track of my current y position.

And this is where it gets odd: I am using the following method to determine the height of a text (using the Paint objected that I initialized previously - it's called "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();
}

The above method returns the following values for the following texts:

  1. "Hello World" returns a height of 12
  2. "A camera instance can be used to compute 3D transformations and generate a matrix." returns a height of 16
  3. "Introducing Android Design: The place to learn about principles, building blocks, and patterns for creating world-class Android user interfaces. Whether you're a UI professional or a developer playing that role, these docs show you how to make good design decisions, big and small." returns a height of 16

It makes sense to me, that number 2 and 3 return a greater height than number 1 but if one line has a height of 12 (as number one does) - it makes no sense, that multiple lines have a height of 16 ?

Am I missing something here? There is a convenience method for measuring the width of a text (using an instance of paint and call measureText("myText") which works perfectly, however I am quite at a loss, when it comes to the height, as the above given results don't make any sense to me.

EDIT

I am aware, that getTextBounds probably does no auto-wrapping of multi-lined text, and that's ok, I already wrote a method for splitting text, but even if it just measures one line, the above given length values still seem unlikely.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

倾`听者〃 2025-01-14 08:20:45

我认为这是因为“compute”中的“p”延伸到基线以下,而“Hello World”仅包含基线以上的字母。

由于行距不应该取决于文本恰好包含哪些特定字母,因此您可能正在寻找 Paint.FontMetrics 可以通过 Paint.getFontMetrics()。计算descent - ascent +leading以获得建议的基线距离(因为ascent具有负值)。

I think it is because the "p" in "compute" extends below the baseline whereas "Hello World" only contains letters that are above the baseline.

Since the line distance should not depend on what specific letters your text happens to consist of you are probably looking for Paint.FontMetrics which can be obtained via Paint.getFontMetrics(). Compute descent - ascent + leading to get the recommended baseline distance (because ascent has a negative value).

抱猫软卧 2025-01-14 08:20:45

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

Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float textHeight = fm.descent - fm.ascent;

如果你想要高度,你应该使用

float lineHeight = fm.bottom - fm.top + fm.leading;

Leading是可选的行间距,所以如果你需要获取行高你可以包括它。但如果你只想要文本高度,那么你可以忽略它。

注意

  • 我从来没有真正见过leading0以外的任何东西,据我所知,它甚至在TextView源代码 (及其相关的布局, StaticLayout 等)。如果我错了,请纠正我。因此,将其排除在高度计算之外可能是安全的,但我对此并不完全确定。

另请参阅

There is a small error in the accepted answer. If you want the text height, you should use

Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float textHeight = fm.descent - fm.ascent;

And if you want the line height, you should use

float lineHeight = fm.bottom - fm.top + fm.leading;

Leading is optional interline spacing, so if you need to get the line hight you can include it. But if you just want the text height, then you can leave it off.

Note

  • I've never actually seen leading be anything else than 0, and as far as I can tell it even seems to be ignored in the TextView source code (and its associated Layout, StaticLayout, etc.). Please correct me if I'm wrong. So it is probably safe it leave it out of line hight calulations, but I'm not completely sure about that.

See also

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文