10

When using Canvas and drawText() method I see a different rendering on Android 4.2.1.

Below 4.2:

enter image description here

For Android 4.2.1 (Nexux 7) I get:

enter image description here

As you can see the text Consumption is very tight. Seems to be a kerning problem introduced in 4.2.1. The Paint used to draw text is nothing special:

titlePaint = new Paint();
titlePaint.setAntiAlias(true);
titlePaint.setColor(0xffffffff);
titlePaint.setTextSize(0.125f);
titlePaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
titlePaint.setTextAlign(Align.CENTER);
titlePaint.setLinearText(true);

If I don't use titlePaint.setLinearText(true) I get a strange result on 4.2.1 as you can see there:

Android 4.2 on Nexus 7: canvas.drawText() not working correctly

EDIT:

This strange behaviour has been reported to the Android team: http://code.google.com/p/android/issues/detail?id=39755 but it's still not a "official" issue.

EDIT (2):

Some rumors claim that the problem is a textSize < 1.0f...

Community
  • 1
  • 1
Seraphim's
  • 12,559
  • 20
  • 88
  • 129

4 Answers4

14

Workaround, that I'm currently using:

scalePaint.setTextSize(1.5f);

then, in onDraw method:

canvas.save();
canvas.scale(0.01f, 0.01f);
canvas.drawText(""+i, 0.5f*100, 0.8f*100, scalePaint);                  
canvas.restore();

As you can see, I'm rescaling back the position of the text, so it's where it's supposed to be.

scana
  • 2,785
  • 2
  • 25
  • 49
  • I vote up for your response because you're the first suggesting a workaround for this incredible issue. Thanks (and vote for the question, maybe someone else will see it and help us!). – Seraphim's Feb 12 '13 at 16:13
  • 2
    To be honest, I'm not the first, I've found it somewhere else, I'll post link to it as soon as possible. Since it's android bug, I'm not sure there will be real solution to the problem instead of silly workarounds. – scana Feb 12 '13 at 16:17
  • I'm still waiting a response from Google as you can see here: http://gc.codehum.com/p/android/issues/detail?id=39755. I think you're the first here on StackOverflow. If it's not true please give the link where you found that solution! :) And yes, you're honest! – Seraphim's Feb 12 '13 at 16:35
  • And finally, I accept your answer. No one has found a final solution or official documentation that explain this behaviour. I don't know how this workaround will impact on performance but a lot of my customer will be happy... Thanks, anyway. – Seraphim's Feb 20 '13 at 17:13
10

I answer my own question after accepting the only response that proposed a workaround for my specific issue. That could be a "nice" and "definitive" solution:

public static void drawTextOnCanvasWithMagnifier(Canvas canvas, String text, float x, float y, Paint paint) {
        if (android.os.Build.VERSION.SDK_INT <= 15) {
            //draw normally
            canvas.drawText(text, x, y, paint);
        }
        else {
            //workaround
            float originalTextSize = paint.getTextSize();
            final float magnifier = 1000f;
            canvas.save();
            canvas.scale(1f / magnifier, 1f / magnifier);
            paint.setTextSize(originalTextSize * magnifier);
            canvas.drawText(text, x * magnifier, y * magnifier, paint);
            canvas.restore();
            paint.setTextSize(originalTextSize);
        }
    }
Seraphim's
  • 12,559
  • 20
  • 88
  • 129
  • 1
    I like your answer very much and I couldn't help but replace 1000 by 1024 for magnifier (hoping it will be more optimized somewhere deep down...) – Couitchy Jan 27 '16 at 17:20
0

This is a bug in Android and while it's already submitted to the bug tracker you might want to +1 it there to get some attention: Issue 39755

florian h
  • 1,162
  • 1
  • 10
  • 24
  • Yes, I'm currently participating in the reporting. I've been contacted by Android team, but it's still not marked as "real" issue. They're still investigating... Thank you to reporting the correct link to the Google page. Do you have the same problem? – Seraphim's Jan 03 '13 at 22:13
  • This is my other question: http://stackoverflow.com/questions/13941270/android-4-2-on-nexus-7-canvas-drawtext-not-working-correctly/13971632#13971632 – Seraphim's Jan 03 '13 at 22:36
0

Use this function to draw correctly with word wrap, new line break and text alignment features -

static void drawTextWithStaticLayout(Canvas canvas, float x, float y, String text, int wrapWidth, TextPaint paint,Layout.Alignment alignment) {
    if (android.os.Build.VERSION.SDK_INT <= 15) {
        StaticLayout sl = new StaticLayout(text,paint, wrapWidth, alignment,1.0f,0.0f,false);
        sl.draw(canvas);
    }
    else {
        float originalTextSize = paint.getTextSize();
        final float magnifier = 1000f;
        canvas.save();
            canvas.translate(x,y);
            canvas.scale(1f / magnifier, 1f / magnifier);
            paint.setTextSize(originalTextSize * magnifier);
            StaticLayout sl = new StaticLayout(text,paint, (int)magnifier*wrapWidth, alignment,1.0f,0.0f,false);
            sl.draw(canvas);
        canvas.restore();
        paint.setTextSize(originalTextSize);
    }
}
MbPCM
  • 457
  • 5
  • 12