【问题标题】:Gettextbounds in android在android中获取文本边界
【发布时间】:2011-04-19 09:55:19
【问题描述】:

我们过去常常找到适合给定文本的矩形,例如,如果在 gettextbounds api 中给出“TESTING”,它将给出一个适合给定字符串“TESTING”的矩形,但任何人都可以澄清矩形长度的基础计算出来的,是否会考虑字体大小,我可以这样检查吗?

1) 我尝试过的方式 CharSequence 文本 = getText(); canvas.drawText(text, 0, text.length(), mTextX, mTextY, getPaint());

    Paint pt = new Paint ( );
    pt.setTextSize(10);

    TextPaint tp = getPaint();
    String string = "haa";
    Rect currentBounds = new Rect ( );
    //this.setTextSize(/* TypedValue.COMPLEX_UNIT_PX */ 10, /* fontPixelSize*Home.fltFontRatio */ 32);

    tp.getTextBounds((String) text, 0, text.length(), currentBounds );

    Log.e ( " ", "Desired Text " +text);
    Log.e ( " ", "first Ondraw Left " +currentBounds.left);
    Log.e ( " ", "Ondraw Top" +currentBounds.top);
    Log.e ( " ", "Ondraw right " +currentBounds.right);
    Log.e ( " ", "Ondraw bottom " +currentBounds.bottom);

    pt.setTextSize(20);


    tp.getTextBounds((String) text, 0, text.length(), currentBounds );

    Log.e ( "", "Desired Text " +text);
    Log.e ( " ", "Second Ondraw Left " +currentBounds.left);
    Log.e ( " ", "Ondraw Top" +currentBounds.top);
    Log.e ( " ", "Ondraw right " +currentBounds.right);
    Log.e ( "Nrace ", "Ondraw bottom " +currentBounds.bottom);

2) 我尝试的第二种方法

    TextPaint tp = getPaint();
    String string = "haa";
    Rect currentBounds = new Rect ( );
    this.setTextSize(/* TypedValue.COMPLEX_UNIT_PX */ 10, /* fontPixelSize*Home.fltFontRatio */ 32);               

    tp.getTextBounds(string, 0, string.length(), currentBounds );

    Log.e ( " ", "first Left " +currentBounds.left);
    Log.e ( " ", "Top" +currentBounds.top);
    Log.e ( " ", "right " +currentBounds.right);
    Log.e ( " ", "bottom " +currentBounds.bottom);

    this.setTextSize(/* TypedValue.COMPLEX_UNIT_PX */ 10, /* fontPixelSize*Home.fltFontRatio */ 10);

    tp.getTextBounds(string, 0, string.length(), currentBounds );

    Log.e ( " ", "Sefond Left " +currentBounds.left);
    Log.e ( " ", "Top" +currentBounds.top);
    Log.e ( " ", "right " +currentBounds.right);
    Log.e ( "", "bottom " +currentBounds.bottom);

在上述两种方法中,我试图找出给定文本大小的各种矩形大小。如果这不是一个好方法,请通过发布一些示例代码来告诉我。简单地说,我必须找到适合各种字体大小的文本“TESTING”的各种矩形。

提前致谢。

【问题讨论】:

    标签: android


    【解决方案1】:

    我发现这部分 API 很混乱,但我想我几乎理解它是如何工作的。对 getTextBounds() 的调用返回最小的矩形,该矩形将包含由后续调用 drawText() 绘制的所有字符,其中 x=0 和 y=0。这在API reference 上的表述略有不同。 Paint 中可能影响文本外观的所有内容都会被考虑在内。这是一个例子:

    Rect bounds = new Rect();
    
    Paint paint = new Paint();
    paint.setTextAlign(Align.LEFT);
    paint.setTypeface(typeface);
    paint.setTextSize(textSize);
    paint.getTextBounds(text, 0, text.length(), bounds);
    

    矩形之所以有这样的exotic坐标是因为当你用drawText()绘制文本时,x和y相对的原点取决于你选择的Paint的印刷属性.例如 y 是相对于基线的,它既不在字体上方也不在字体下方,但通常在中间的某个地方敲击它。出于这个原因,边界矩形将(通常)具有负顶部和正底部。负数 top 表示文本顶部 高于 基线(y 向上减小),而正数 bottom 表示文本底部 低于 基线(y 增加下降)。有趣的是,当您测量诸如“Hi”之类的字符串时,底部可能为 0,因为这些字符没有 低于基线 部分。相反,当您测量像 "Hg" 这样的字符串时,您可能会得到一个正的底部,因为 g 的 story 低于基线。不过,我不确定如何估计水平位置。

    话虽如此,要绘制已计算出边界的文本,您可以这样做:

    canvas.drawText(text, -bounds.left, -bounds.top, paint);
    

    这会将文本绘制在画布的左上角附近。左上角的坐标是 (0, 0) 所以要在你周围移动文本只需要添加你想要的位移量:

    canvas.drawText(text, -bounds.left + yourX, -bounds.top + yourY, paint);
    

    另一个例子:如果你想创建一个包含文本的位图,并且你想完全适合可用空间,你可以这样做:

    Bitmap bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.drawText(text, -bounds.left, -bounds.top, paint);
    

    如果你想在左边、右边、顶部和底部留下几个像素,比如说2,你可以这样做:

    Bitmap bitmap = Bitmap.createBitmap(bounds.width() + 4, bounds.height() + 4, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.drawText(text, -bounds.left + 2, -bounds.top + 2, paint);
    

    【讨论】:

    • 我已经尝试过几次,我很确定答案是正确的。它对你有用吗?如果是这种情况,也许您可​​以接受答案,它可能会帮助处于相同情况的其他人。
    • 完全按照这个答案中的说明做对我不起作用,有时它仍然有几个像素。但是,使用 Paint.measureText() 总是有效的。
    • 这可能是stackoverflow.com/questions/7549182/… 中提到的问题,但是关于getTextBounds 的问题,特别是澄清计算矩形长度的基础,是否如果我可以这样检查的话,我会考虑字体大小.
    • 有关 getTextBounds 的信息,谢谢。尽管对于来到这里的任何人来说,Alex Chi 看起来都是一个更可靠的解决方案,因为它使用 measureText 来获取宽度。 (正如OP所说“如果这不是一个好方法请告诉我”)
    • 啊,Prizoff 解释了stackoverflow.com/a/15398496/199364 这个答案中没有明确说明的内容。要使用边界正确测量所需宽度,必须执行bounds.left + bounds.width()。也许left 是第一个可见像素之前的微小空间,width 是实际绘制像素的宽度。
    【解决方案2】:

    有一些细微差别,所以最好看一次... 红色矩形显示文本边界,x,y - 任意坐标(文本边界左下点)

    Rect textBounds = new Rect();
    Paint textPaint = new Paint();
    Paint rectPaint = new Paint();
    String text = "java m";
    
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    
        textPaint.setTextSize(100);
        textPaint.getTextBounds(text, 0, text.length(), textBounds);
    
        canvas.drawText(text, x, y, textPaint);
    
        rectPaint.setColor(Color.RED);
        rectPaint.setStyle(Paint.Style.STROKE);
    
        canvas.drawRect(
                x,                       // left
                y - textBounds.height(), // top
                x + textBounds.width(),  // right
                y,                       // bottom
                rectPaint);
    }
    

    text = "Hello Worlds"

    text = "java m"

    【讨论】:

    • Paint.Align textAlign = Paint.Align.LEFT;在这种情况下应该是这个。
    【解决方案3】:

    我的解决方案:

    class Pos {
      public int X;
      public int Y;
    }
    public static void getTextPositionAndRealBound(Paint paint, String text, int x, int y, Pos pos, Rect bound) {
      paint.getTextBounds(text, 0, text.length(), bound);
      // in X
      bound.left = x;
      bound.right = (int)(paint.measureText(text) + 0.5); // .5f to 1
    
      // in Y
      y = y - bound.top;
      bound.top = y;
      bound.bottom = bound.height();
    
      // reset the position
      pos.X = x;
      pos.Y = y;
    }
    

    你知道 X 是对的,Y 在 getTextBounds 的边界坐标下。

    该解决方案可以获取文本的位置和实际边界。您可以将文本移动到任何位置,只需编辑 var - pos 并在调用 Canvas.drawText 时使用它:

    Pos pos;
    Rect bound;
    getTextPositionAndRealBound(paint, text, x, y, pos, bound);
    canvas.drawText(text, pos.X, pos.Y, paint);
    

    注意:感谢@ToolmakerSteve 的建议

    【讨论】:

    • 如果重复调用不同的文本,在每次调用之前初始化 pos.Y 很重要,因为这个方法会改变它。这就是修改输入参数的危险。恕我直言,风险较小的是(Paint paint, String text, int x, int y, Pos outPos, Rect bound),其中xy 是所需的位置。然后..getTextBounds(..); outPos.x = x; bound.left = x; bound.right = ..; outPos.Y = y - bound.top; bound.top = y; ..注意不再有本地声明int y,因为我们直接传入y
    • @ToolmakerSteve 对,我相信你是 Java 专业人士。我会修改它。非常感谢。
    【解决方案4】:

    这是一种适合我的方法:使用 Paint.measureText(text) 获取 text 的宽度和 Paint.getTextBounds(text, 0, text.length(), bounds) 获取 text 的高度 (height = bounds.height())

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      相关资源
      最近更新 更多