4

I have tried to create a custom class in order to implement a text as drawable but I am unable to set Typeface to Paint. Below is the code implementation of the custom class (i.e. TextDrawable).

Here I want to get the context of Application to call the method getAssets(), but here I'm unable to call the method getContext().

public class TextDrawable extends Drawable {
    private final String text;
    private final Paint paint;

    public TextDrawable(String text) {
        this.text = text;
        this.paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setTextSize(35f);
        //paint.setTypeface(Typeface.createFromAsset(**getContext().getAssets()**, "fonts/Montserrat-Regular.otf"));
        paint.setAntiAlias(true);
        paint.setTextAlign(Paint.Align.RIGHT);
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawText(text, 0, 10, paint);
    }

    @Override
    public void setAlpha(int alpha) {
        paint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        paint.setColorFilter(cf);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Surya Mouly
  • 110
  • 10
  • make sure you un-comment the code line,If that was intentional can you try converting otf file to ttf using and online tool. – Ismail Iqbal Nov 21 '17 at 11:13
  • What problems are you having, exactly? – Mike M. Nov 21 '17 at 11:34
  • hi, @IsmailIqbal comment is intentional and there is no problem with the file format. I am not able to get getContext().getAssets() in this class – Surya Mouly Nov 21 '17 at 11:50
  • I am not able to get getContext().getAssets() in this class @MikeM. – Surya Mouly Nov 21 '17 at 11:51
  • Please refer to this [question](https://stackoverflow.com/questions/6042977/android-set-custom-font-to-a-paint) and check the most rated answer. – dalla92 Nov 21 '17 at 11:51
  • `Drawable` doesn't have a `Context` field or a `getContext()` method, inherently. You'll have to pass one in the constructor. Alternatively, you could pass the already-created `Typeface` in the constructor. – Mike M. Nov 21 '17 at 11:53
  • @MikeM. thanks it helped. – Surya Mouly Nov 21 '17 at 13:07

2 Answers2

4

I am not able to get getContext().getAssets() in this class.

You have to pass a Context object as a parameter to your class's constructor:


    public class TextDrawable extends Drawable {
        ...

        public TextDrawable(Context context, String text) {
            paint.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/Montserrat-Regular.otf"));
            ...
        }
        ...
    }

azizbekian
  • 60,783
  • 13
  • 169
  • 249
3

Drawable object does not have a Context. So as suggested by @azizbekian and @Mike M, you have two options.

Pass Context in constructor

public TextDrawable(Context context, String text) {
    paint.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/Montserrat-Regular.otf"));
    ...
}

Note that this approach will create a new Typeface instance everytime you use this Drawable, and this is generally a bad practice which also directly affects performance.

Pass Typeface in constructor

public TextDrawable(String text, Typeface typeface) {
    paint.setTypeface(typeface);
    ...
}

This approach is better, as you have the possibility of using a single instance of Typeface for multiple objects, related or unrelated to this Drawable.

Extending the latter approach, you may create a Static TypefaceProvider as below. This makes sure that you have only One Instance of the Typeface at all times.

TypefaceProvider

public class TypefaceProvider
{
    private static Map<String, Typeface> TYPEFACE_MAP = new HashMap<>();

    public static Typeface getTypeFaceForFont(Context context, String fontFile)
    {
        if (fontFile.length() <= 0) throw new InvalidParameterException("Font filename cannot be null or empty");
        if (!TYPEFACE_MAP.containsKey(fontFile))
        {
            try
            {
                Typeface typeface = Typeface.createFromAsset(context.getAssets(), "fonts/"+fontFile);
                TYPEFACE_MAP.put(fontFile, typeface);
            }
            catch (Exception e)
            {
                throw new RuntimeException(String.format("Font file not found.\nMake sure that %s exists under \"assets/fonts/\" folder", fontFile));
            }
        }

        return TYPEFACE_MAP.get(fontFile);
    }
}
Community
  • 1
  • 1
anemo
  • 1,327
  • 1
  • 14
  • 28
  • okay, how about if I create a static context at application class level and then use that context here. if there are any cons. of doing that. – Surya Mouly Nov 22 '17 at 05:42
  • 1
    Static Context in Application is the "Non-Recommended, Preferred" method. Everyone uses it but no one recommends it. So, yes you can, just don't tell anyone that I suggested it! >:) – anemo Nov 22 '17 at 15:48