Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining text size for Canvas.drawText() in res/values/dimens.xml

In a Scrabble-like word game app I am trying to draw black letters and values on yellow tiles.

While this works at Android emulators under Windows and Mac:

Mac screenshot

Windows screenshot

This doesn't work (the text size is too big) on real devices like Moto G, Nexus 1 and 4:

Real devices

I define the text sizes of 60sp and 20sp (I've tried dp too) in res/values/dimens.xml:

<resources>
    <dimen name="big_tile_letter">60sp</dimen>
    <dimen name="big_tile_value">20sp</dimen>
</resources>

And then use them in my BigTile.java class:

    int letterSize = context.getResources().getDimensionPixelSize(R.dimen.big_tile_letter);
    mLetterPaint = new Paint();
    mLetterPaint.setTextSize(letterSize);
    mLetterPaint.setAntiAlias(true);

    Rect letterBounds = new Rect();  
    mLetterPaint.getTextBounds(letter, 0, letter.length(), letterBounds);
    mLetterX = 0.45f * (width - letterBounds.width());
    mLetterY = 0.45f * (height + letterBounds.height());

    canvas.drawText(letter, mLetterX, mLetterY, mLetterPaint);

What am I doing wrong?

like image 969
Alexander Farber Avatar asked Nov 07 '14 16:11

Alexander Farber


3 Answers

If what you want to is to convert a value from the R.dimen.something into pixels so:

float textSize = getResources().getDimensionPixelSize(R.dimen.something);

If what you want is to supply a manual value or something like that:

float maxTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, maxTextSize, getResources().getDisplayMetrics());
like image 191
TacB0sS Avatar answered Oct 06 '22 20:10

TacB0sS


One thing that comes to mind is that you are using sp values, which depend on the user setting in Settings / Display / Font Size. Can you check whether the setting is like Large or so - this would apply an additional scaling on your font size. Also, I believe for 2.x devices the default setting is different than for 4.x devices (not sure though).

You could try use dp values and see if that makes any difference.

like image 24
Flo Avatar answered Oct 06 '22 21:10

Flo


The problem is that setTextSize gets the size value in SP, not in pixels. In your case getDimensionPixelSize converts sp to pixels, and then setTextSize treats the pixels as sp, and scales up again.

public void setTextSize(float size)

Set the default text size to the given value, interpreted as "scaled pixel" units. This size is adjusted based on the current density and user font size preference.

To fix this, you can call

setTextSize (TypedValue.COMPLEX_UNIT_PX, letterSize)
like image 41
yoah Avatar answered Oct 06 '22 20:10

yoah