In this tutorial, we’ll explain how to set up android custom fonts in TextViews and Buttons in our application.
Android Custom Fonts
Android SDK comes with a set of standard fonts that can be styled by using a few XML attributes. Let’s look at them.
Let’s club android:fontFamily
and android:textStyle
and display the different variants of a TextView.
The styles.xml which contains the different style variants is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="Regular"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="Italic"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="Bold"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="BoldItalic"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">bold|italic</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="RegularCondensed"> <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif-condensed</item> </style> <style name="ItalicCondensed"> <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif-condensed</item> </style> <style name="BoldCondensed"> <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif-condensed</item> </style> <style name="Casual"> <item name="android:fontFamily">casual</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">Casual</item> </style> <style name="Cursive"> <item name="android:fontFamily">cursive</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">Cursive</item> </style> <style name="RegularMono"> <item name="android:fontFamily">monospace</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">mono space</item> </style> <style name="ItalicMono"> <item name="android:fontFamily">monospace</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">monospace</item> </style> <style name="BoldMono"> <item name="android:fontFamily">monospace</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">monospace</item> </style> <style name="RegularMonoSerif"> <item name="android:fontFamily">serif-monospace</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">serif-monospace</item> </style> <style name="ItalicMonoSerif"> <item name="android:fontFamily">serif-monospace</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">serif-monospace</item> </style> <style name="BoldMonoSerif"> <item name="android:fontFamily">serif-monospace</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">serif-monospace</item> </style> </resources> |
The activity_main.xml is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.journaldev.customfonts.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Regular" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Italic" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularCondensed" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/ItalicCondensed" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/BoldCondensed" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Casual" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Cursive" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularMono" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/ItalicMono" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/BoldMono" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularMonoSerif" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/ItalicMonoSerif" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/BoldMonoSerif" /> </LinearLayout> <img class="alignnone wp-image-33065 size-full" src="https://all-learning.com/wp-content/uploads/2016/12/android-standard-font-variants-output1.png" alt="android-standard-font-variants-output" width="1200" height="628" /> |
To set custom fonts on a TextView/Button/EditText object, the Typeface property is used.
The Typeface class specifies the typeface and intrinsic style of a font.
To set a typeface over a TextView we invoke the method setTypeface().
Following are the Typeface constants that can be used.
- BOLD
- BOLD_ITALIC
- ITALIC
- NORMAL
To set custom fonts on our Views, we first need to import the font files into our project.
Font files generally come up in two types .ttf (True Type Font) and .otf (Open Type Font).
Android Custom Fonts Project Structure
In the above image a new folder assets has been added under the main directory.
Android Custom Fonts Code
We’ve created another layout namely activity_custom_fonts.xml
for setting custom fonts on our Views.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.journaldev.customfonts.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Bold" android:textSize="28sp" android:id="@+id/ambleBold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Light" android:textSize="28sp" android:id="@+id/ambleLight" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Regular" android:textSize="28sp" android:id="@+id/ambleRegular" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans Regular" android:textSize="28sp" android:id="@+id/opRegular" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans-Italic" android:id="@+id/opItalic" android:textSize="28sp" /> <Button android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Pacifico" android:id="@+id/pacifico"/> </LinearLayout> |
We’re setting our custom fonts in the java code. The MainActivity.java is given below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class MainActivity extends AppCompatActivity { TextView ambleBold, ambleLight, ambleRegular, openSansItalic, openSansRegular; Button btn; private String A_BOLD= "Amble-Bold.ttf"; private String A_LIGHT="Amble-Light.ttf"; private String A_REGULAR= "Amble-Regular.ttf"; private String O_ITALIC= "OpenSans-Italic.ttf"; private String O_REGULAR="OpenSans-Regular.ttf"; private String P_REGULAR="Pacifico.ttf"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_fonts); ambleBold=(TextView)findViewById(R.id.ambleBold); ambleLight=(TextView)findViewById(R.id.ambleLight); ambleRegular=(TextView)findViewById(R.id.ambleRegular); openSansRegular=(TextView)findViewById(R.id.opRegular); openSansItalic=(TextView)findViewById(R.id.opItalic); btn=(Button)findViewById(R.id.pacifico); ambleBold.setTypeface(Typeface.createFromAsset(getAssets(), A_BOLD)); ambleLight.setTypeface(Typeface.createFromAsset(getAssets(), A_LIGHT)); ambleRegular.setTypeface(Typeface.createFromAsset(getAssets(), A_REGULAR)); openSansRegular.setTypeface(Typeface.createFromAsset(getAssets(), O_REGULAR)); openSansItalic.setTypeface(Typeface.createFromAsset(getAssets(), O_ITALIC)); btn.setTypeface(Typeface.createFromAsset(getAssets(), P_REGULAR)); } } |
In the above code we’re calling createFromAsset() method on the Typeface class to create a new instance of the Typeface. An instance of the application’s AssetManager is called by passing getAssets()
as the first parameter. The custom font asset file path is passed as a string in the second parameter. Since we’ve placed the font files in the root of assets directory, passing the font filenames would suffice.
Note: Setting external fonts using android:typeface doesn’t work
We end up with the following output when the application is run.
Isn’t it a time consuming and redundant task to set the typeface individually for each of the views?
We need a better alternative. Our answer lies in Custom Views. In the next section, we’ll be creating a Custom TextView class and define custom XML attributes to set the external fonts in the XML layout itself.
Our Updated Project Structure is given below
Before we implement our CustomTextView.java, let’s look into the TypeFactory.java
class as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class TypeFactory { private String A_BOLD= "Amble-Bold.ttf"; private String A_LIGHT="Amble-Light.ttf"; private String A_REGULAR= "Amble-Regular.ttf"; private String O_ITALIC= "OpenSans-Italic.ttf"; private String O_REGULAR="OpenSans-Regular.ttf"; Typeface ambleBold; Typeface ambleLight; Typeface ambleRegular; Typeface openSansItalic; Typeface openSansRegular; public TypeFactory(Context context){ ambleBold = Typeface.createFromAsset(context.getAssets(),A_BOLD); ambleLight = Typeface.createFromAsset(context.getAssets(),A_LIGHT); ambleRegular = Typeface.createFromAsset(context.getAssets(),A_REGULAR); openSansItalic = Typeface.createFromAsset(context.getAssets(),O_ITALIC); openSansRegular = Typeface.createFromAsset(context.getAssets(),O_REGULAR); } } |
The above code essentially creates a custom typeface font for each of the font files. We can now use the class variables in our CustomTextView to set the font accordingly.
The CustomTextView.java
class is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
public class CustomTextView extends TextView { private int typefaceType; private TypeFactory mFontFactory; public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); applyCustomFont(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); applyCustomFont(context, attrs); } public CustomTextView(Context context) { super(context); } private void applyCustomFont(Context context, AttributeSet attrs) { TypedArray array = context.getTheme().obtainStyledAttributes( attrs, R.styleable.CustomTextView, 0, 0); try { typefaceType = array.getInteger(R.styleable.CustomTextView_font_name, 0); } finally { array.recycle(); } if (!isInEditMode()) { setTypeface(getTypeFace(typefaceType)); } } public Typeface getTypeFace(int type) { if (mFontFactory == null) mFontFactory = new TypeFactory(getContext()); switch (type) { case Constants.A_BOLD: return mFontFactory.ambleBold; case Constants.A_LIGHT: return mFontFactory.ambleLight; case Constants.A_REGULAR: return mFontFactory.ambleRegular; case Constants.O_LIGHT: return mFontFactory.openSansItalic; case Constants.O_REGULAR: return mFontFactory.openSansRegular; default: return mFontFactory.ambleBold; } } public interface Constants { int A_BOLD = 1, A_LIGHT = 2, A_REGULAR = 3, O_LIGHT = 4, O_REGULAR=5; } } |
R.styleable.CustomTextView
is defined inside the attrs.xml file as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomTextView"> <attr name="font_name"> <enum value="1" name="ambleBold"/> <enum value="2" name="ambleLight"/> <enum value="3" name="ambleRegular"/> <enum value="4" name="openSansItalic"/> <enum value="5" name="openSansRegular"/> </attr> </declare-styleable> </resources> |
The attribute font_name is the custom attribute we’ll be using in the XML layout.
Our updated activity_custom_fonts.xml
layout is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" xmlns:app="https://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.journaldev.customfonts.MainActivity"> <com.journaldev.customfonts.CustomTextView app:font_name="ambleBold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Bold" android:textSize="28sp" android:id="@+id/ambleBold" /> <com.journaldev.customfonts.CustomTextView app:font_name="ambleLight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Light" android:textSize="28sp" android:id="@+id/ambleLight" /> <com.journaldev.customfonts.CustomTextView app:font_name="ambleRegular" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Regular" android:textSize="28sp" android:id="@+id/ambleRegular" /> <com.journaldev.customfonts.CustomTextView app:font_name="openSansRegular" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans Regular" android:textSize="28sp" android:id="@+id/opRegular" /> <com.journaldev.customfonts.CustomTextView app:font_name="openSansItalic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans-Italic" android:id="@+id/opItalic" android:textSize="28sp" /> <Button android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Pacifico" android:id="@+id/pacifico"/> </LinearLayout> |
The MainActivity.java code now would just require setting the Button typeface.
Note: A CustomButton Custom View can be created in a similar way. Try that out!
This brings an end to this tutorial. You can download the Android CustomFonts Tutorial from the below link.