【问题标题】:Android: Measure Text Height on a CanvasAndroid:测量画布上的文本高度
【发布时间】:2012-03-10 23:50:04
【问题描述】:

我目前正在渲染位图,然后我想将其发送到移动打印机。但是,我正在努力测量文本的高度,因此我可以适当地推进 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(就像第一行一样) - 多行的高度为 16 是没有意义的?

我在这里遗漏了什么吗?有一种方便的方法来测量文本的宽度(使用paint的实例并调用 measureText("myText") 效果很好,但是当涉及到高度时,我很茫然,正如上面给出的结果对我没有任何意义。

编辑

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

【问题讨论】:

    标签: android paint android-canvas


    【解决方案1】:

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

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

    【讨论】:

    • 我计算了以上三个给定文本的基线距离(根据您的计算),它总是返回 19。这是否意味着,如果我取 19 的高度,仍然有足够的空间下一行不与当前行重叠?非常感谢您!
    • 这是字体的一个特性,你不必为不同的文字重复计算。无论文本由什么字符组成,您都希望距离始终相同。是的,线条不会重叠。
    • 非常感谢 - 这就是我所做的,现在渲染我的位图工作正常 :) 。我在 MyRenderer 的构造函数中初始化了一次“行高”。
    【解决方案2】:

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

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

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

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

    Leading 是可选的行间距,因此如果您需要获得行高,您可以包含它。但是如果你只是想要文字高度,那么你可以不设置它。

    注意

    • 我实际上从未见过leading0 以外的任何东西,据我所知,它甚至似乎在TextView source code 中被忽略(及其相关的LayoutStaticLayout、等等。)。如果我错了,请纠正我。所以它可能是安全的,让它脱离高度计算,但我对此并不完全确定。

    另请参阅

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-17
      • 2011-04-08
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2010-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多