I\'m trying to define a GUI layout using XML files in Android. As far as I can find out, there is no way to specify that your widgets should use a custom font (e.g. one you\
I might have a simple answer for the question without extending the TextView and implementing a long code.
Code :
TextView tv = (TextView) findViewById(R.id.textview1);
tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));
Place the custom font file in assets folder as usual and try this. It works for me. I just dont understand why peter has given such a huge code for this simple thing or he has given his answer in old version.
Fontinator is an Android-Library make it easy, to use custom Fonts. https://github.com/svendvd/Fontinator
Also can be defined in the xml without creating custom classes
style.xml
<style name="ionicons" parent="android:TextAppearance">
<!-- Custom Attr-->
<item name="fontPath">fonts/ionicons.ttf</item>
</style>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/ionicons"
android:text=""/>
</LinearLayout>
A quick note, because I just always forgot where to put the fonts, its that the font must be inside assets
and this folder resides in the same level that res
and src
, in my case its assets/fonts/ionicons.ttf
Updated Added root layout because this method needs xmlns:app="http://schemas.android.com/apk/res-auto"
to work
Update 2 Forgot about a library that I've installed before called Calligraphy
You can extend TextView to set custom fonts as I learned here.
TextViewPlus.java:
package com.example;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
public class TextViewPlus extends TextView {
private static final String TAG = "TextView";
public TextViewPlus(Context context) {
super(context);
}
public TextViewPlus(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
String customFont = a.getString(R.styleable.TextViewPlus_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface tf = null;
try {
tf = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface: "+e.getMessage());
return false;
}
setTypeface(tf);
return true;
}
}
attrs.xml: (in res/values)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextViewPlus">
<attr name="customFont" format="string"/>
</declare-styleable>
</resources>
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res/com.example"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.TextViewPlus
android:id="@+id/textViewPlus1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:text="@string/showingOffTheNewTypeface"
foo:customFont="saxmono.ttf">
</com.example.TextViewPlus>
</LinearLayout>
You would put "saxmono.ttf" in the assets folder.
There are serious memory concerns with this method. See chedabob's comment below.
This might be a little late, but you need to create a singleton class that returns the custom typeface to avoid memory leaks.
TypeFace class:
public class OpenSans {
private static OpenSans instance;
private static Typeface typeface;
public static OpenSans getInstance(Context context) {
synchronized (OpenSans.class) {
if (instance == null) {
instance = new OpenSans();
typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf");
}
return instance;
}
}
public Typeface getTypeFace() {
return typeface;
}
}
Custom TextView:
public class NativelyCustomTextView extends TextView {
public NativelyCustomTextView(Context context) {
super(context);
setTypeface(OpenSans.getInstance(context).getTypeFace());
}
public NativelyCustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setTypeface(OpenSans.getInstance(context).getTypeFace());
}
public NativelyCustomTextView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
setTypeface(OpenSans.getInstance(context).getTypeFace());
}
}
By xml:
<com.yourpackage.views.NativelyCustomTextView
android:id="@+id/natively_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="20dp"
android:text="@string/natively"
android:textSize="30sp" />
Programmatically:
TextView programmaticallyTextView = (TextView)
findViewById(R.id.programmatically_text_view);
programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
.getTypeFace());
You can make easily custom textview class :-
So what you need to do first, make Custom textview
class which extended with AppCompatTextView
.
public class CustomTextView extends AppCompatTextView {
private int mFont = FontUtils.FONTS_NORMAL;
boolean fontApplied;
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, context);
}
public CustomTextView(Context context) {
super(context);
init(null, context);
}
protected void init(AttributeSet attrs, Context cxt) {
if (!fontApplied) {
if (attrs != null) {
mFont = attrs.getAttributeIntValue(
"http://schemas.android.com/apk/res-auto", "Lato-Regular.ttf",
-1);
}
Typeface typeface = getTypeface();
int typefaceStyle = Typeface.NORMAL;
if (typeface != null) {
typefaceStyle = typeface.getStyle();
}
if (mFont > FontUtils.FONTS) {
typefaceStyle = mFont;
}
FontUtils.applyFont(this, typefaceStyle);
fontApplied = true;
}
}
}
Now , every time Custom text view call and we will get int value from attribute int fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1)
.
Or
We can also get getTypeface() from view which we set in our xml (android:textStyle="bold|normal|italic"
). So do what ever you want to do.
Now, we make FontUtils
for set any .ttf font into our view.
public class FontUtils {
public static final int FONTS = 1;
public static final int FONTS_NORMAL = 2;
public static final int FONTS_BOLD = 3;
public static final int FONTS_BOLD1 = 4;
private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();
static Typeface getFonts(Context context, String name) {
Typeface typeface = TYPEFACE.get(name);
if (typeface == null) {
typeface = Typeface.createFromAsset(context.getAssets(), name);
TYPEFACE.put(name, typeface);
}
return typeface;
}
public static void applyFont(TextView tv, int typefaceStyle) {
Context cxt = tv.getContext();
Typeface typeface;
if(typefaceStyle == Typeface.BOLD_ITALIC) {
typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
}else if (typefaceStyle == Typeface.BOLD || typefaceStyle == SD_FONTS_BOLD|| typefaceStyle == FONTS_BOLD1) {
typeface = FontUtils.getFonts(cxt, "FaktPro-SemiBold.ttf");
} else if (typefaceStyle == Typeface.ITALIC) {
typeface = FontUtils.getFonts(cxt, "FaktPro-Thin.ttf");
} else {
typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
}
if (typeface != null) {
tv.setTypeface(typeface);
}
}
}