Android 4.2.1 wrong character kerning (spacing)
Asked Answered
C

4

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...

Conni answered 20/12, 2012 at 14:19 Comment(2)
What exactly is your question?Negress
Why texts are rendered on Android 4.2.1 in that way? What can I do to fix this unwanted behaviour?Placida
P
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.

Phoenician answered 12/2, 2013 at 16:2 Comment(4)
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!).Placida
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.Phoenician
I'm still waiting a response from Google as you can see here: 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!Placida
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.Placida
C
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);
        }
    }
Conni answered 20/2, 2013 at 20:13 Comment(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...)Cuckoopint
K
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

Konstance answered 3/1, 2013 at 20:40 Comment(2)
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?Placida
This is my other question: #13941770Placida
D
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);
    }
}
Dormouse answered 19/3, 2018 at 8:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.