Androidでデフォルトのフォントを設定したい

# 概要

デフォルトフォントを適応するときのアプローチのまとめと、自作のライブラリの紹介です。

DroidKaigiの資料で触れていますが、Qiitaにまとめておきます。
https://speakerdeck.com/takahirom/support-libraryfalsedownloadable-fontsyaemojicompatnidui-ying-sitaapuriwozuo-rou

# デフォルトフォントの適応方法について
以下5つぐらいの方法が存在します。
* 手動で指定する方法
* テーマによる方法
* リフレクションによる方法 [StackOverFlow](https://stackoverflow.com/questions/2711858/is-it-possible-to-set-a-custom-font-for-entire-of-application/16883281#16883281)
* [chrisjenx/Calligraphy](https://github.com/chrisjenx/Calligraphy)による方法
* 激推し → [takahirom/DownloadableCalligraphy](https://github.com/takahirom/DownloadableCalligraphy)による方法

## 手動で指定する方法
デフォルトのフォントを指定せずに手動で指定していく方法です。これでほとんど問題ないです。ただToolbarのタイトルやBottomNavigation、TabLayoutなどを自分でちゃんと属性を調べて、大きさなども調べ、自分で指定していく必要があります、ただ頑張って指定していけばなんとかなります。

DroidKaigi公式アプリではマテリアルデザインの[Dense scriptの記載](https://material.io/guidelines/style/typography.html#typography-styles)に則って、指定していっています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/27388/8061654d-770d-815f-60e7-f938c4eaf518.png)


```xml
<TextView
    android:id="@+id/speaker_name"
    android:textAppearance="@style/TextAppearance.App.Body1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
```

(DroidKaigiアプリより)

```xml
<style name=“TextAppearance.App.Title"
       parent="TextAppearance.AppCompat.Title">
    <item name="android:textSize">21sp</item>
    <item name="android:fontFamily">@font/notosans_medium</item>
</style>

<style name="TextAppearance.App.Subhead" 
       parent="TextAppearance.AppCompat.Subhead">
    <item name="android:textSize">17sp</item>
    <item name="android:fontFamily">@font/notosans_regular</item>
</style>
```

## テーマによる方法
TextViewだけであればtextViewStyleを使ったり、以下のように全てのtextAppearanceを指定していくことで、大体設定することが出来ます。しかし、デフォルトの大きさの指定を調べたりする手間や、テーマファイルは汚れますし、なかなか保守が大変になります。

```xml
<style name=“AppTheme" parent="Theme.AppCompat.Light">
   <item name=“android:textAppearance">@style/TextAppearance.hogehoge</item>
   <item name=“android:textAppearanceSmall”>@style/TextAppearance..</item>
   <item name="android:textAppearanceButton">@style/TextAppearance…</item>
   <item name=“android:textAppearanceMediumInverse”>@style/TextAppearance…</item>
。。。。
```

## リフレクションによる方法 [StackOverFlow](https://stackoverflow.com/questions/2711858/is-it-possible-to-set-a-custom-font-for-entire-of-application/16883281#16883281)
これはAppCompatThemeでは動きません。一般的なアプリでは利用できないものとなります。

## [chrisjenx/Calligraphy](https://github.com/chrisjenx/Calligraphy)による方法

デフォルトフォントを指定したい場合、今のデファクトスタンダードなライブラリは[chrisjenx/Calligraphy](https://github.com/chrisjenx/Calligraphy)だと思われます。

去年、Font Resource、Downloadable Fontの発表されました。その時に**Calligraphy is dead**と作者が言っていて、**CalligraphyはFont Resourceの仕組みが適応**できず、またツイート前の5/16日が最終コミットで**開発が止まっています**。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/27388/b9997a76-941e-2d1f-3cee-9a96add71480.png)

## [takahirom/DownloadableCalligraphy](https://github.com/takahirom/DownloadableCalligraphy)による方法
そこで自分がライブラリを作りました。
**CalligraphyをベースにFont Resourceの仕組みを適応した**のがこのライブラリになります。
これはDroidKaigiアプリの初期に導入して利用しており、うまく動いています。
DownloadableCalligraphyという名前ですが、Font Resourceを指定できるので、アプリにフォントを埋め込むBundled Resourceも普通に指定できます。
**みなさんがスターしていただけると、前例が増えて、安心して使えるようになる**のではと思います。


```java
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
  .setDefaultFont(R.font.roboto_regular)
  .build());
```

```java
@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
```


# まとめ
他に選択肢があれば教えてください。なければ[takahirom/DownloadableCalligraphy](https://github.com/takahirom/DownloadableCalligraphy)に**スターをつけてください**。