The cause of

Recently, there was a need to make an AppWidget, but I rejected it because it was extremely difficult and restrictive, but I couldn’t help it, so let’s do it.

I thought it was pretty simple, a list of data, and then some basic data, two days to do it, and then show it to the UI, and here’s the conversation with the UI.

UI: Did you copy the Blue Lake?

Me: What’s the problem? (I wonder… I copied the blue Lake!

UI: Look, your font at this time is different from my picture!

Me: Uh… Okay, I’ll go back and figure it out, and you can send me the font.

The original font

We haven’t worked with fonts in a long time, but Android has four premade fonts for us. Take a look:

  1. Normal (Normal font, default font used by the system)
  2. Sans (Sans Serif font)
  3. Serif font
  4. Monospace (equal width font)

Here’s an example:


      
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="Normal"
        android:textColor="# 000"
        android:textSize="30sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:fontFamily="sans-serif"
        android:text="Sans"
        android:textColor="# 000"
        android:textSize="30sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:fontFamily="serif"
        android:text="Serif"
        android:textColor="# 000"
        android:textSize="30sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:fontFamily="monospace"
        android:text="Monospace"
        android:textColor="# 000"
        android:textSize="30sp" />

</LinearLayout>
Copy the code

The example above is very simple, a linear layout wrapped around the system described above prefabricated four fonts, take a look at the effect:

In fact, it is not only used like the above, the above four can also be combined with each other, but also have different effects, you can try yourself:

Fonts are not restricted to layout files, they can also be changed in code:

// Set the font style
mainText.typeface = Typeface.SANS_SERIF
mainText.typeface = Typeface.SERIF
Copy the code

If nothing special is required, these fonts will suffice for most development needs, and they can be bolded and italicized.

Use three-party fonts

But UI does not think android prefabricated several fonts look good, just want to get a different font 😂, that is no way, let’s see how to set it up.

The introduction of the font

If you want to use a font with three fonts, the first step is to introduce the next font file with a.ttf suffix. You need to put the font file in the assets->fonts folder.

use

It is very easy to use, using AssetsManager to get the font file, and then directly using setTypeFace method to set the font:

// Read the font from asset to get Typeface based on the path
val tf = Typeface.createFromAsset(assets, "Fonts/your font name.ttf")
// Set the font
mainText.typeface = tf
Copy the code

The problem

So far, the above content is baidu Android font can come out of the content, but!! RemoteView sets the value of an AppWidget, but RemoteView does not have any font setting methods.

Baidu did not find the result for a long time, so I wondered if I could change the default font of one of the TextView fonts to the one I wanted through reflection in the Application. Then set the TextView in the AppWidget by setting the theme to change the font.

Let’s start with the Application font replacement code:

class App : Application() {

    override fun onCreate(a) {
        super.onCreate()
        updateFont()
    }

    private fun updateFont(a) {
        val regular = Typeface.createFromAsset(
            assets,
            "Fonts/your font name.ttf"
        )
        replaceFont(regular)
    }


    @SuppressLint("DiscouragedPrivateApi")
    private fun replaceFont(newTypeface: Typeface) {
        valnewMap: MutableMap<String? , Typeface> = HashMap() newMap["MONOSPACE"] = newTypeface
        try {
            val staticField = Typeface::class.java
                .getDeclaredField("sSystemFontMap")
            staticField.isAccessible = true
            staticField[null] = newMap
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

}
Copy the code

Let’s set this in the theme:

<! -- font theme. -->
<style name="FontAppTheme" parent="Theme.AppCompat">
    <item name="android:typeface">monospace</item>
</style>
Copy the code

Then you can set it in the TextView:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:text="O"
    android:textColor="# 000"
    android:textSize="30sp"
    android:theme="@style/FontAppTheme" />
Copy the code

The solution

The above method is too cumbersome and uses reflection, which is not friendly. Just think about going through the official documentation, maybe there’s something that works.

Sure enough… The first sentence of the official document made me laugh…

What? Just create a font folder in res as if it were an image and put the font in it to use it as if it were an image.

Then what am I doing up there?

Well… Encounter problems or as little as possible Baidu, see more official documents.

There is no need to get fonts from AssetsManager as before. You can get fonts from Resources:

val tf = resources.getFont(R.font.myfont)
mainText.typeface = tf
Copy the code

This is the font of official documentation address: developer. The android, Google. Cn/guide/topic…

conclusion

Ah, in fact, a very simple thing, and in Android 8.0 has already implemented things, now immediately all Android 12 I did not know, shame ah!!

Ok, that’s it, you have problems in the future or read more documents… Don’t be like me.