Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is There a Way to Use a Font from Compose Resources with a View?

I am writing a suite of apps. Some will be multiplatform, using Compose Multiplatform for the UI. One will be only deployed on Android.

I defined the design system using Compose Multiplatform and Compose Resources. This includes a custom font, in commonMain/composeResources/font/ of my design system module:

Android Studio project view, showing custom font resource

This works well, even from a regular Android project. However, that Android project also uses a third-party library, where I need to use the same custom font. That library uses the legacy View system, so I have a second copy of my custom font in res/font/ of the module that needs it.

Everything runs and looks correct, but the result is that I have two copies of this font. The font is over 800KB, and ideally I would only have one copy.

Is there a way that I can use a font defined in Compose Resources with a View?

Right now, I am using the Android font resource in a style, via <item name="android:fontFamily">@font/inter_variable</item>. Probably I can switch that to configuring the font in Kotlin. So, for example, if there is a way I can get a Typeface for the Compose Resources font, I may be able to use that with setTypeface() on a TextView.

like image 700
CommonsWare Avatar asked Oct 31 '25 11:10

CommonsWare


2 Answers

Since Compose Multiplatform 1.7.3, The resources are getting packed as Android assets already,

Therefore Typeface.createFromFile(File(Res.getUri('font/path/in/multiplat/commons/'))) should work.

like image 57
Nima G Avatar answered Nov 03 '25 02:11

Nima G


Using Nima's answer as inspiration, I wound up with:

@OptIn(ExperimentalResourceApi::class)
public fun createTypefaceFromComposeResource(context: Context, fontFileName: String): Typeface? = Typeface.createFromAsset(
    context.assets,
    Uri.parse(Res.getUri("font/$fontFileName")).path?.replace("/android_asset/", "")
)

Usage would be something like:

myTextView.typeface = createTypefaceFromComposeResource(context, "myAwesomeFont.ttf")

Res.getUri() returns a string representation of an Android asset Uri: file:///android_asset/path/to/the/resource. Right now I'm playing it safe, parsing the Uri and using path to get rid of the scheme. Unfortunately, the android_asset segment is considered to be part of the path, which is why I remove it using replace(). If you wanted, you could skip the Uri.parse() and use replace() for the whole initial segment.

like image 35
CommonsWare Avatar answered Nov 03 '25 01:11

CommonsWare



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!