问题
There's a HUGE problem in my code wherein I am loading a font in my assets\fonts\
folder from a custom TextView
class. The first problem is that it crashes on 4.0 devices with the exception Caused by: java.lang.RuntimeException: native typeface cannot be made
. I was using the same process here with the method:
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context) {
super(context);
}
public void setTypeface(Typeface tf, int style) {
if (style == Typeface.BOLD) {
super.setTypeface(Typeface.createFromAsset(
getContext().getAssets(), "fonts/hirakakupronbold.ttf"));
} else if (style == Typeface.ITALIC) {
super.setTypeface(Typeface.createFromAsset(
getContext().getAssets(), "fonts/hirakakupronitalic.ttf"));
} else {
super.setTypeface(Typeface.createFromAsset(
getContext().getAssets(), "fonts/hirakakupron.ttf"));
}
}
}
Notice that I'm using the extension .ttf
, and I found that this is causing the RunTimeException
. So I converted the respective fonts with a .otf
extensions, and now it runs already in 4.0 devices but has memory leaks basing here. There are workarounds here but I don't know how to use/call it. Any help would do, thank you.
回答1:
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.
回答2:
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
回答3:
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,
回答4:
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.
来源:https://stackoverflow.com/questions/20942671/runtimeexception-native-typeface-cannot-be-made-or-memory-leak-for-custom-textv