RuntimeException: native typeface cannot be made or memory leak for custom TextView loading font

与世无争的帅哥 提交于 2019-11-30 15:57:44

Okay, so I finally figured that instantiating a TypeFace object inside a TextView class would cause so much load each time that same TextView is instantiated. This caused my app to lag and resulted to OutOfMemoryException eventually. So what I did was to create a different custom TypeFace class that would call my fonts from the assets so that it instantiates from the TypeFace class and not from the TextView class.

Here's my TypeFaces class:

public class TypeFaces {

    private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();

    public static Typeface getTypeFace(Context context, String assetPath) {
        synchronized (cache) {
            if (!cache.containsKey(assetPath)) {
                try {
                    Typeface typeFace = Typeface.createFromAsset(
                            context.getAssets(), assetPath);
                    cache.put(assetPath, typeFace);
                } catch (Exception e) {
                    Log.e("TypeFaces", "Typeface not loaded.");
                    return null;
                }
            }
            return cache.get(assetPath);
        }
    }
}

And the custom TextView class:

public class TextViewHirakaku extends TextView {

    public TextViewHirakaku(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TextViewHirakaku(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TextViewHirakaku(Context context) {
        super(context);
    }

    public void setTypeface(Typeface tf, int style) {
        if (style == Typeface.BOLD) {
            super.setTypeface(TypeFaces.getTypeFace(getContext(),
                    "fonts/hirakakupronbold.ttf"));
        } else if (style == Typeface.ITALIC) {
            super.setTypeface(TypeFaces.getTypeFace(getContext(),
                    "fonts/hirakakupronitalic.ttf"));
        } else {
            super.setTypeface(TypeFaces.getTypeFace(getContext(),
                    "fonts/hirakakupron.ttf"));
        }
    }
}

Notice that I'm now calling getTypeFace method from TypeFaces class here.

If you're having this issue on Android Studio then put your assets under main directory instead of putting it under res directory.

Also in font naming use lowercase letters and underscores only, e.g. my_font.ttf

That worked like charm for me

If you are extending this view from xml then try using it this way::

public class MyTextView extends TextView {

  public MyTextView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      init();
  }

 public MyTextView(Context context, AttributeSet attrs) {
      super(context, attrs);
      init();
  }

 public MyTextView(Context context) {
      super(context);
      init();
 }


public void init() {
    Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/hirakakupronbold.ttf");
    setTypeface(tf);

}

}

Its working fine for me. Make separate class extending TextView for each typeface style.to To apply it, replace your "TextView" with "com.yourpackage.MyTextView"

Regards,

In my case, the XML namespace prefix that I was using for my custom view (costum) wasn't set right:

xmlns:costum="http://schemas.android.com/apk/tools"

All I had to do is to change it to

xmlns:costum="http://schemas.android.com/apk/res-auto"

& it worked.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!