Custom fonts can significantly enhance the visual appeal and branding of your Android application. Using custom fonts in your app can make it stand out and provide a unique user experience. In this guide, we’ll explore how to add custom fonts to your Android project (under res/font/
) and apply them programmatically in Kotlin XML development.
Why Use Custom Fonts?
- Branding: Use fonts that match your brand identity.
- User Experience: Improve readability and visual appeal.
- Uniqueness: Differentiate your app from others with distinctive typography.
Step 1: Add Custom Font Files to Your Project
The first step is to add your custom font files to your Android project. These files typically come in .ttf
(TrueType Font) or .otf
(OpenType Font) formats. Here’s how to add them:
1. Create a font
Directory
If it doesn’t already exist, create a font
directory under the res
directory. This is where you will store all your font files.
app/
└── src/
└── main/
└── res/
└── font/
└── # Font files (.ttf or .otf) will go here
2. Copy Font Files
Copy your .ttf
or .otf
font files into the res/font/
directory. For example:
app/
└── src/
└── main/
└── res/
└── font/
├── my_custom_font_regular.ttf
└── my_custom_font_bold.ttf
3. Create Font Resource XML (Optional)
To take advantage of Android’s font family feature (especially for handling different font weights like regular and bold), create a font resource XML file. In the font
directory, create a new XML file (e.g., my_custom_font.xml
):
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<font
android:fontStyle="normal"
android:fontWeight="400"
android:font="@font/my_custom_font_regular"
app:fontStyle="normal"
app:fontWeight="400"
app:font="@font/my_custom_font_regular" />
<font
android:fontStyle="normal"
android:fontWeight="700"
android:font="@font/my_custom_font_bold"
app:fontStyle="normal"
app:fontWeight="700"
app:font="@font/my_custom_font_bold" />
</font-family>
In this XML:
android:fontStyle
: Specifies whether the font is italic or normal.android:fontWeight
: Specifies the weight of the font (e.g., 400 for regular, 700 for bold).android:font
: Points to the actual font file.
Note that if you’re supporting older versions of Android (API < 26), you’ll need to include the app:
attributes.
Step 2: Apply Custom Fonts in XML
You can directly apply custom fonts in your XML layouts by referencing them. There are two primary ways to do this:
1. Using android:fontFamily
If you’ve created a font resource XML (e.g., my_custom_font.xml
), you can use the android:fontFamily
attribute in your TextView
.
<TextView
android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, Custom Font!"
android:fontFamily="@font/my_custom_font" />
The android:fontFamily
attribute allows you to specify the font family defined in the XML resource.
2. Direct Reference (Without Font Family XML)
Alternatively, you can directly reference a specific font file using the android:typeface
attribute (though android:fontFamily
is recommended for better flexibility).
<TextView
android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, Custom Font!"
android:typeface="normal"
android:fontFamily="@font/my_custom_font_regular" />
Here, android:fontFamily
is directly pointing to the font file. Although android:typeface
is set to normal (to ensure it doesn’t interfere), the fontFamily
is the one effectively setting the font.
Step 3: Apply Custom Fonts Programmatically in Kotlin
You can also apply custom fonts programmatically in your Kotlin code. This is useful when you need to dynamically change the font or apply it to views created programmatically.
1. Get a Typeface
Instance
Use the ResourcesCompat.getFont()
method to obtain a Typeface
instance from your font resource.
import androidx.core.content.res.ResourcesCompat
import android.graphics.Typeface
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView: TextView = findViewById(R.id.myTextView)
val typeface: Typeface? = ResourcesCompat.getFont(this, R.font.my_custom_font)
textView.typeface = typeface
}
}
Here, ResourcesCompat.getFont()
is used to load the font resource specified by R.font.my_custom_font
. Then, textView.typeface
is set to this typeface.
2. Handle Font Loading Errors
It’s a good practice to handle potential errors that might occur when loading fonts.
import androidx.core.content.res.ResourcesCompat
import android.graphics.Typeface
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView: TextView = findViewById(R.id.myTextView)
val typeface: Typeface? = try {
ResourcesCompat.getFont(this, R.font.my_custom_font)
} catch (e: Exception) {
Log.e("FontError", "Failed to load font", e)
null
}
textView.typeface = typeface
}
}
This code includes a try-catch
block to log any errors that occur while loading the font, ensuring your app doesn’t crash and provides helpful debugging information.
Complete Example
Here’s a complete example of using custom fonts in an Android project:
1. Create the res/font/my_custom_font.xml
file:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<font
android:fontStyle="normal"
android:fontWeight="400"
android:font="@font/my_custom_font_regular" />
</font-family>
2. Layout XML (res/layout/activity_main.xml
):
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, Custom Font!"
android:textSize="24sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
3. Kotlin Code (MainActivity.kt
):
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.core.content.res.ResourcesCompat
import android.graphics.Typeface
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView: TextView = findViewById(R.id.myTextView)
val typeface: Typeface? = ResourcesCompat.getFont(this, R.font.my_custom_font)
textView.typeface = typeface
}
}
Conclusion
Adding and applying custom fonts in your Android application can significantly improve its visual appeal and user experience. Whether you choose to apply fonts directly in XML layouts or programmatically in Kotlin, the key is to ensure your font files are correctly added to the res/font/
directory and properly referenced. By following the steps outlined in this guide, you can easily integrate custom fonts and elevate your app’s design.