Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android canvas drawText y-position of text

I'm using a Canvas to create a Drawable with some background and some text. The drawable is used as a compound drawable inside an EditText.

The text is drawn via drawText() on the canvas, but I do have an issue with the y-position of the drawn text in some cases. In those cases parts of some characters are cut off (see image links).

Characters without positioning issue:

http://i50.tinypic.com/zkpu1l.jpg

Characters with positioning issue, text contains 'g', 'j', 'q', etc.:

http://i45.tinypic.com/vrqxja.jpg

You can find a code snippet to reproduce the issue below.

Does any expert know how to determine the proper offset for the y position?

public void writeTestBitmap(String text, String fileName) {    // font size    float fontSize = new EditText(this.getContext()).getTextSize();    fontSize+=fontSize*0.2f;    // paint to write text with    Paint paint = new Paint();     paint.setStyle(Style.FILL);      paint.setColor(Color.DKGRAY);    paint.setAntiAlias(true);    paint.setTypeface(Typeface.SERIF);    paint.setTextSize((int)fontSize);    // min. rect of text    Rect textBounds = new Rect();    paint.getTextBounds(text, 0, text.length(), textBounds);    // create bitmap for text    Bitmap bm = Bitmap.createBitmap(textBounds.width(), textBounds.height(), Bitmap.Config.ARGB_8888);    // canvas    Canvas canvas = new Canvas(bm);    canvas.drawARGB(255, 0, 255, 0);// for visualization    // y = ?    canvas.drawText(text, 0, textBounds.height(), paint);     try {       FileOutputStream out = new FileOutputStream(fileName);       bm.compress(Bitmap.CompressFormat.JPEG, 100, out);    } catch (Exception e) {       e.printStackTrace();    } } 
like image 527
darksaga Avatar asked May 15 '12 18:05

darksaga


2 Answers

I think it's probably a mistake to assume that textBounds.bottom = 0. For those descending characters, the bottom parts of those characters are probably below 0 (which means textBounds.bottom > 0). You probably want something like:

canvas.drawText(text, 0, textBounds.top, paint); //instead of textBounds.height()

If your textBounds is from +5 to -5, and you draw text at y=height (10), then you'll only see the top half of the text.

like image 82
Tim Avatar answered Sep 23 '22 11:09

Tim


I believe that if you want to draw text near the upper left corner you should do this:

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

And you can move around the text by summing the desired amount of displacement to the two coordinates:

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

The reason why this works (at least for me) is that getTextBounds() tells you where drawText() would draw the text in the event that x=0 and y=0. So you have to counteract this behavior by subtracting the displacement (textBounds.left and textBounds.top) introduced by the way text is handled in Android.

In this answer I elaborate a little more on this topic.

like image 22
damix911 Avatar answered Sep 22 '22 11:09

damix911