I was also busy with this problem.
Unfortunately, I have not yet been able to establish the native source, but I'm sure that the text dimensions (both getTextBounds () and measureText ()) are very different from the real text output, especially for small font sizes (as you can see in the screenshot of Moritz ) I believe that measurement methods use the width of the float for char, and the actual text output uses int (presumably due to performance). This, of course, will fail if you need an absolutely accurate size (for example, for autosave). I experimented a bit with a monospace font. This image shows some of these experiments:
.
The text scale in these experiments was set by automatic scaling.
On the top line, I created the fields in integer increments. They correspond to the output of Android. You see, the last cipher does not fit the screen!
In the second line, the boxes were created in increments of the float. The boxes fit the screen better, but they don't match the Android output!
In the last line, the fields were incremented using a float increment, and the text was displayed char on char in the same increment. Both boxes and symbols are perfect.
In my conclusion, it is currently not possible to set the text output on Android to exact width. The problem does not seem to be in measurement methods that are reasonably accurate. The problem is that you cannot set the exact width of the text using setTextSize ().
Try to reproduce the following:
float width = 100; // define a width which should be achieved m_textPaint.setTextSize( 100 ); // set a text size surely big enough Rect r = new Rect(); String s = new String("This is a test text"); m_textPaint.getTextBounds( s, 0, s.length(), r ); // measure the text with a random size float fac = width / r.width(); // compute the factor, which will scale the text to our target width Log.i( "MyTestOutput", "current text width:" + r.width() ); Log.i( "MyTestOutput", "wanted text width:" + width ); Log.i( "MyTestOutput", "factor:" + fac ); Log.i( "MyTestOutput", "expected result:" + (float) r.width() * fac ); m_textPaint.setTextSize( m_textPaint.getTextSize() * fac ); m_textPaint.getTextBounds( s, 0, s.length(), r ); // now final measurement: whats the real width? Log.i( "MyTestOutput", "real result:" + r.width() );
I get the output:
05-26 12: 18: 18.420: I / MyTestOutput (23607): current text width: 1125
05-26 12: 18: 18.425: I / MyTestOutput (23607): width of the required text: 100.0
05-26 12: 18: 18.425: I / MyTestOutput (23607): coefficient: 0.08888889
05-26 12: 18: 18.425: I / MyTestOutput (23607): expected result: 100.0
05-26 12: 18: 18.430: I / MyTestOutput (23607): actual result: 94
So, in my opinion, the only way to achieve very precisely autoscaled text is a) to autoscale it by measuring and setting the text size b) to display its char on char using its own calculation.
Unfortunately, this only works for monospace fonts. For other fonts this will be harder, but also possible.