Gettextbounds in android

后端 未结 4 1584
生来不讨喜
生来不讨喜 2020-12-13 16:20

We used to find the rectangle which fits the given text, for example if give \"TESTING\" in gettextbounds api it will give a rectangle that fits the given string \"TESTING\"

相关标签:
4条回答
  • 2020-12-13 16:25

    Here's a way that works for me: use Paint.measureText(text) to get text's width and Paint.getTextBounds(text, 0, text.length(), bounds) to get text's height (height = bounds.height())

    0 讨论(0)
  • 2020-12-13 16:39

    There are some nuances, so it is better once to see... Red rectangle shows text bounds, x,y - any coordinates (of left lower point of the text bounds)

    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"

    0 讨论(0)
  • 2020-12-13 16:47

    I find this part of the API quite confusing, however I think I almost understood how it works. A call to getTextBounds() returns the smallest rectangle that would enclose all the characters drawn by a subsequent call to drawText() with x=0 and y=0. This is stated in slightly different words on the API reference. Everything that is in Paint and could affect the appearance of the text is taken into account. Here's an example:

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

    The reason why the rectangle has such exotic coordinates is because when you draw text with drawText(), the origin to which x and y are relative depends on the typographical properties of the Paint that you selected. For instance y is relative to the baseline, which is neither above nor below the font, but usually strikes it somewhere across the middle. For this reason the bounds rectangle will have (usually) a negative top and a positive bottom. The negative top means that the top of the text is above the baseline (y decreases going up), while the positive bottom means that the bottom of the text is below the baseline (y increases going down). It is interesting to note that when you measure a string such as "Hi" the bottom is likely to be 0, because those characters do not have a below the baseline part. On the contrary, when you measure a string like "Hg" you are likely to get a positive bottom, because the story of the g is below the baseline. I'm not sure how the horizontal position is estimated, though.

    With this said, to draw the text of which you have computed the bounds you can do:

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

    This will draw the text near to the upper left corner of the canvas. The coordinates of the upper left corner are (0, 0) so to move the text around you only have to add your desired amount of displacement:

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

    Another example: if you want to create a bitmap that contains text, and you want to fit exactly the available space, you can do:

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

    If you want to leave a few pixels to the left, right, top and bottom, let's say 2, you can do:

    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);
    
    0 讨论(0)
  • 2020-12-13 16:48

    My solution:

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

    You know that the X is right and the Y is down in the coord of the bound by getTextBounds.

    The solution can get the position and real bound of text. You can move the text to any position, just edit the var - pos and use it when call Canvas.drawText like this:

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

    Note: thanks for @ToolmakerSteve advice

    0 讨论(0)
提交回复
热议问题