Recently I experienced the problem of fake bold and italics using the font family in Android.
I would like to explain this problem and share its solution.
Font Family
Since API 26 was released, an ability to combine fonts into font families has appeared.
Font family is a set of fonts with their font styles and weights.
You can create a new font family as an XML resource and access it as a single item, instead of referencing each style and weight as separate resources.
In this way, the system will be able to choose the correct font depending on the text style that you use.
Example of the 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/lobster_regular" />
<font
android:fontStyle="italic"
android:fontWeight="400"
android:font="@font/lobster_italic" />
</font-family>
The attribute fontStyle determines individual font style - normal (normal) or cursive (italic).
fontWeight establishes font weight, a/k/a font saturation.
And of course, font sets a font which will be used at the given fontWeight and fontStyle.
Font Weight
This standard came from web-development. Value is set from 100 to 900 with a 100 pitch.
The table below shows some common names of saturation:
Usually it is enough to specify only fonts for normal glyph (- 400) and standard bold one (- 700) in the font family file.
For details about font saturation, look here.
Fake Italic
When the system can’t find a suitable font for bold or cursive text, Android compensates it by stretching characters for fake bold and by tilting for fake italic.
I created an app which shows the differences between fake styles and the real ones using Lobster Two font as an example:
Using a fake font, you may notice that the text is more flattened. Even worse, this makes it difficult to read because of the smearing of letters and wrong tilt.
Solution
In this example I create lobster_two.xml font family file with fonts for normal, cursive, bold, and bold cursive text:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
<font
app:fontStyle="normal"
app:fontWeight="400"
app:font="@font/lobster_two_normal" />
<font
app:fontStyle="italic"
app:fontWeight="400"
app:font="@font/lobster_two_italic" />
<font
app:fontStyle="normal"
app:fontWeight="700"
app:font="@font/lobster_two_bold" />
<font
app:fontStyle="italic"
app:fontWeight="700"
app:font="@font/lobster_two_bold_italic" />
</font-family>
I also created lobster_two_incomplete.xml with a font only for normal text:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
<font
app:fontStyle="normal"
app:fontWeight="400"
app:font="@font/lobster_two_normal" />
</font-family>
And I was switching back and forth between them by pressing the switch.
When lobster_two_incomplete.xml was used instead of lobster_two.xml the font was artificially stretched and tilted.
To prevent this from happening, all sorts of styles in the font family file need to be defined, and this file always must be used as a font.
Using this in the code:
// Correct
val typeFace = resources.getFont(R.font.lobster_two)
textView.setTypeface(typeFace, Typeface.BOLD)
// Incorrect
textView.typeface = resources.getFont(R.font.lobster_two_bold)
// Incorrect
val typeFace = resources.getFont(R.font.lobster_two_incomplete)
textView.setTypeface(typeFace, Typeface.BOLD)
// Incorrect
val typeFace = resources.getFont(R.font.lobster_two_normal)
textView.setTypeface(typeFace, Typeface.BOLD)
Using in xml:
// Correct
<TextView
...
android:fontFamily="@font/lobster_two"
android:textStyle="bold|italic"/>
// Incorrect
<TextView
...
android:fontFamily="@font/lobster_two_bold_italic"/>
// Incorrect
<TextView
...
android:fontFamily="@font/lobster_two_incomplete"
android:textStyle="bold|italic"/>
// Correct
<TextView
...
android:fontFamily="@font/lobster_two"
android:textStyle="bold"/>
// Incorrect
<TextView
...
android:fontFamily="@font/lobster_two_bold"/>
// Incorrect
<TextView
...
android:fontFamily="@font/lobster_two_normal"
android:textStyle="bold"/>
Written by: Veniamin Vynohradov, Android Developer, Zoolatech.