Typeface — android.graphicsパッケージのAndroid SDKのクラスで、フォントのデザインを表し、TextViewや他のUIコンポーネントのテキストカスタマイズに使用されます。Typefaceはフォントファミリー、そのウエイト(normal, bold)およびスタイル(normal, italic)を定義します。Google Developersによると、TypefaceはTTF、OTFファイル、XMLフォント、システムリソースからの読み込みをサポートしています。これはAndroidアプリケーションにおけるタイポグラフィ管理の中心的なクラスです。
ポイント
Typeface — フォント情報をエンカプセルするAndroidクラスです:そのファミリー(Roboto, Arial, Serif)とスタイル修飾子(bold, italic)。iOSのUIFontとは異なり、Typefaceにサイズ情報は含まれません — テキストサイズはTextViewのtextSizeプロパティまたはSpannableのTextStyleによって別途設定されます。Typefaceはフォントのデザインとファミリーのみに責任を持ちます。
このクラスはすべてのAPIレベルで利用可能です。Android 4.4以前は、Typefaceは制限されたシステムフォントのみをサポートしていました:DEFAULT、DEFAULT_BOLD、MONOSPACE、SERIF、SANS_SERIF。Android 8.0(API 26)からはXMLリソースを通じたカスタムフォントの読み込みサポートが追加され、Android 10では変化フォントのサポートが追加されました。
Androidはいくつかの組み込みTypefaceインスタンスを提供しています:Typeface.DEFAULT — システムフォントRoboto(Material)またはNoto(AOSP)、DEFAULT_BOLD — 太字バージョン、MONOSPACE — コード用の等幅フォント、SERIF — セリフフォント(Noto Serif)、SANS_SERIF — サンセリフ(Noto Sans)。これらの定数はコンテキストなしで利用可能で、ファイル読み込みパーミッションは不要です。
Androidシステムは、システムUI、タイトル、キャプション、通知を含むすべてのテキストをレンダリングするためにTypefaceを使用します。各アプリケーションは、テーマ(android:fontFamily)またはプログラマティックにsetTypeface()を使ってデフォルトフォントをオーバーライドできます。TypefaceはTextViewから継承されたすべてのコンポーネント(ボタン、EditText、カスタムビュー)に適用されます。
Android 8.0+では、res/fontにフォントを追加し、XMLリソースを通じて使用できます。フォントファイル(TTFまたはOTF)をres/fontに配置すると、R.font.font_name参照が作成されます。TypefaceはResourcesCompat.getFont(context, R.font.font_name)を通じて読み込まれます。この方法は、フォントがAPKにコンパイルされ、ProGuardビルドシステムをサポートするため、推奨されます。
リソースアプローチは、res/fontのXMLファイルを通じたフォントファミリーもサポートしています:異なるデザイン(regular, bold, italic)に対して複数のファイルを指定でき、setTypefaceを呼び出すとシステムが自動的に適切なファイルを選択します。これによりタイポグラフィが簡素化されます — テーマでfontFamilyを設定するだけで、Androidが自動的に正しいファイルを選択します。
Typeface.create(Typeface family, int style)メソッドは、指定されたファミリーとスタイルでフォントインスタンスを作成します。ファミリーにすでにリクエストされたスタイルがある場合は、既存のインスタンスが返されます。スタイルがない場合、Androidはそれを合成します — ベースフォントに偽太字または人工的なイタリックを適用します。
val boldTypeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
val italicTypeface = Typeface.create(Typeface.MONOSPACE, Typeface.ITALIC)
val customTypeface = ResourcesCompat.getFont(context, R.font.montserrat_regular)
textView.typeface = boldTypeface
合成された偽太字は、細いフォントでは品質が低く見えることがあります。最も良い結果を得るには、実際のboldデザインのフォントファイルを使用してください。Typeface.create()は、存在しないスタイルでも例外をスローせず、最も近い利用可能なバリアントを返します。
assetsからTypefaceを読み込むには、Typeface.createFromAsset(assetManager, path)を使用します。フォントはsrc/main/assets/fonts/ディレクトリに配置され、パスはassets相対で指定されます。この方法はすべてのAndroidバージョンで動作しますが、フォントファミリーはサポートされず、デザインごとに特定のファイルを指定する必要があります。
Typeface.createFromFile(File)メソッドは、ファイルシステム上の任意のファイルからフォントを読み込みます。これは、ネットワークからダウンロードされたフォントや、アプリの内部ストレージにコピーされたフォントに便利です。createFromFileもコンテキストが不要であり、バックグラウンドタスクに便利ですが、ファイルは読み取り可能でなければなりません。
createFromAssetを通じてTypefaceを繰り返し読み込むと、デュプリケートオブジェクトが作成される可能性があります。createFromAssetを呼ぶたびにファイルが再読み込みされます。HashMapを使用してTypefaceキャッシュを実装することが推奨されます。このキャッシュでは、ファイルパスをキーとし、読み込まれたインスタンスを値とします。これは、異なるフォント種類を使用するリストで特に重要です。
object TypefaceCache {
private val cache = mutableMapOf<String, Typeface>()
fun getTypeface(context: Context, filename: String): Typeface {
return cache.getOrPut(filename) {
Typeface.createFromAsset(context.assets, "fonts/$filename")
}
}
}
// Usage
val typeface = TypefaceCache.getTypeface(context, "Roboto-Bold.ttf")
メモリ内のキャッシュにより、フォントがアプリケーションセッションで一度だけ読み込まれることが保証されます。構成変更(画面回転)時にも、companionオブジェクトにあるためキャッシュは維持されます。メモリ不足時にキャッシュをクリアするには、WeakHashMapを使用するか、onTrimMemoryをリスニングします。
Typefaceは、setTypeface(Typeface tf)またはsetTypeface(Typeface tf, int style)メソッドを通じてTextViewに適用されます。翌のバリアントでは、現在のフォントに対してスタイル(bold/italic)を変更できます。XMLでは、android:fontFamily属性をフォントやシステムファミリーへの参照とともに使用します。プログラマティックな設定では、setTypeface(monospaceTypeface)を呼ぶと指定されたフォントに置き換えられます。
TypefaceはTextViewの全てのテキストに影響します。単一の行で異なるフォントが必要な場合は、TypefaceSpanを伴うSpannableStringを使用します。TypefaceSpanはTypefaceまたはファミリーを受け入れ、文字範囲に適用されます。これは、ネストされたコンポーネントなしで単一のTextView内でフォントを混組する唯一の方法です。
TypefaceSpanを文字列の一部にのみ適用します。例えば、テキスト内の変数の値は等幅フォントにし、他のテキストはシステムフォントのままにします。SpannableStringを作成し、必要な範囲にMONOSPACE Typefaceを持つTypefaceSpanを設定します。他のテキストは元のTextViewフォントを維持します。
val text = "Code: variableName"
val spannable = SpannableString(text)
spannable.setSpan(
TypefaceSpan(Typeface.MONOSPACE),
5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
ForegroundColorSpan(Color.BLUE),
5, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
テキスト“variableName”は青い等幅フォントで表示され、“Code:”の単語はシステムフォントのままになります。TypefaceSpanは、テキストの各セグメントを精確に制御するために、他のどのようなスパンとも組み合わせることができます。
Androidはいくつかのフォントフォーマットをサポートしています:TrueType (TTF)、OpenType (OTF)、およびAndroid 10からWeb Open Font Format (WOFF2)。TTFとOTFは、カスタムフォントの主要フォーマットです。XMLフォント(Font Family)は独自のフォーマットではなく、各デザインに使用するファイルを説明するものです。
res/fontを通じてカスタムフォントを使用するには、regular、bold、italicのフォントファイルへのパスを指定するファミリーXMLファイルを作成します。その後、アプリのテーマでandroid:fontFamily="@font/custom_family"を指定します。このテーマを使用するすべてのTextViewインスタンスは、各スタイルに対して自動的に正しいデザインを取得します。
ネットワークからダウンロードされたフォントは、filesDirまたはcacheDirに保存し、Typeface.createFromFileを通じて読み込みます。読み込んだ後は、TextViewのTypefaceを更新します。非同期読み込みには、coroutineまたはDownloadManagerを使用し、完了後にHandlerを通じてUIスレッドにポストします。これは、オンデマンドで読み込まれるカスタムタイポグラフィを持つアプリの典型的なシナリオです。
// Save font file to internal storage
val fontFile = File(context.cacheDir, "downloaded-font.otf")
fontFile.outputStream().use { output ->
// inputStream from network
inputStream.copyTo(output)
}
// Create Typeface from file
val downloadedTypeface = Typeface.createFromFile(fontFile)
textView.typeface = downloadedTypeface
読み込む前に、ファイルの利用可能性を確認してください:ファイルが損傷しているか無効な場合、Typeface.createFromFileはRuntimeExceptionをスローします。呼び出しをtry-catchで囲み、エラー時はデフォルトのシステムフォントに戻すことをおすすめします。
Jetpack Composeでは、Android SDKのTypefaceは直接使用されません。代わりに、ComposeはタイポグラフィにFontFamilyとFontWeightを提供しています。FontFamilyはFont.ResourceとFont.Fileを通じて読み込まれます。ComposeのタイポグラフィシステムはMaterialTheme.typographyで定義され、各スタイル(h1, body1, button)にカスタムFontFamilyを割り当てることができます。
リソースからフォントを読み込むには、ComposeはFont(R.font.font_name, weight, style)を使用します。assetsからのフォントはFont(assetPath = "fonts/custom.otf", weight, style)を通じて読み込みます。フォントを定義した後、Typographyに渡され、その後MaterialTheme.typography.bodyLargeや他のスタイルを通じて適用されます。
Android SDKを通じて作成された既存のTypefaceがある場合、それをComposeでTypefaceAdapterを通じて使用するか、Typefaceに基づいてFontFamilyを作成することができます。Typeface.createからTypefaceを取得し、FontFamily.Custom(listOf(Font(typeface)))に渡します。ただし、Font.Resourceを使用したネイティブなアプローチがComposeに最適化されているため、こちらをおすすめします。
ファイルからのフォント読み込みは、コストのかかるオペレーションである可能性があります。Typeface.createFromAssetまたはTypeface.createFromFileを呼ぶたびに、ディスクからファイルを読み込み、解析し、Typefaceオブジェクトを作成します。1-2MBのフォントでは、コールドスタート時に10-50ミリ秒かかります。カスタムフォントを使用するアプリでは、Typefaceのキャッシュは必須です。
Android SDKは、createFromAssetやcreateFromFileで作成されたフォントをキャッシュしません。Zygoteプロセスでプリロードされるシステムフォントとは異なり、カスタムフォントはアクセスごとに読み込まれます。フォント識別子をキーとしたLruCacheまたはConcurrentHashMapを使用することをおすすめします。10-20インスタンスのキャッシュサイズで、アプリの典型的なフォントセットをカバーできます。
Android 8.0+はXML Font Familyを通じてフォント読み込みを最適化します。XMLレイアウトでandroid:fontFamily="@font/my_family"を指定すると、Androidはフォントを懒悰読み込みします — コンポーネントが表示されるときだけ読み込みます。また、ResourcesCompat.getFont()で読み込まれたフォントは、グローバルプロセスキャッシュに保存されます。これにより、リソースアプローチが最高のパフォーマンスを示します。
RecyclerViewアダプタでTypefaceを使用する際は、onBindViewHolderメソッドでフォントを読み込まないようにしてください。アダプタ作成時に一度読み込むか、事前に読み込んだTypefaceを持つViewHolderを使用します。リストの各項目に独自のフォントが必要な場合は、WeakHashMapを使用したキャッシュを実装し、メモリを節約するために可視位置をスクロールしたらクリアします。
よくある質問
Typeface — プログラマティックな使用のための具体的なフォントインスタンスです。FontFamily — 異なるデザイン(regular, bold, italic)のフォントファイルのグループを記述するXMLリソースです。ランタイムでは、FontFamilyはResourcesCompat.getFontを通じてTypefaceに変換されます。TypefaceはFontFamilyを経由せずに、ファイルから直接作成できます。
Typeface.createFromFile(File)またはTypeface.DEFAULTを使用します。これらのメソッドは、ファイルシステムまたは組み込み定数で動作するため、コンテキストが不要です。assetsやリソースからの読み込みには、AssetManagerおよびアプリリソースへのアクセスが必要なため、コンテキストが必要です。
いいえ、WebViewはフォントを指定するためにCSS font-familyプロパティを使用します。WebViewでカスタムフォントを使用するには、フォントファイルをassetsに置き、CSSで@font-faceを通じて指定します。Typeface Android SDKは、ネイティブのUIコンポーネント(TextViewおよびその継承クラス)でのみ動作します。
はい、Android 10(API 29)からサポートしています。変化フォントはResourcesCompat.getFontまたはTypeface.createFromFileを通じて読み込みます。変化軸(weight, width)を構成するには、ComposeのFontStyleまたはXML属性を使用します。プログラマティックな軸変更は、Skiaの低レベルAPIを通じてのみ可能です。
最もよくある原因は、プロジェクトにフォントファイルがない、ファイル名が間違っている、フォントが損傷している、またはファイルに存在しない合成スタイルが使用されていることです。ファイルがres/fontまたはassetsに追加されていること、およびリソースアプローチの場合は拡張子なしで名前が指定されていることを確認してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。