4

I am looking for a way to easily use custom fonts in a Compose Multiplatform project.

I found that we need to use Font from the androidx.compose.ui.text.platform.Font package. But this object takes in parameter data: ByteArray.

Until now, I haven't found a way to use Font to import a font file from the commonMain resource directory.

How to use custom fonts in the commonMain part of a Compose Multiplatform project?

Thank you for your help!

Vince
  • 2,551
  • 1
  • 17
  • 22
  • You need to set font from resources, check this answer https://stackoverflow.com/a/71123775/10568816 – gavr May 02 '23 at 13:41

3 Answers3

2

The easiest way is to use moko resources : https://github.com/icerockdev/moko-resources

Add the font in commonMain/resources/MR/fonts

for example: PlayfairDisplay-Bold.ttf file

Then load the FontFamily :

val fontFamilyExtraBold: FontFamily = fontFamilyResource(SharedRes.fonts.PlayfairDisplay.extraBold)

And finaly use it in your Typography in your theme. More infos on Moko resources docs.

Louis Duboscq
  • 359
  • 1
  • 3
  • 9
2

There is a easy way to use common resources directory for both android and desktop.

create src/commonMain/resources/ directory inside :shared module. then set the android source sets of android and jvm as follows:

kotlin {
    targetHierarchy.default()

    android {
        compilations.all {
            kotlinOptions {
                jvmTarget = "1.8"
            }
        }
    }

    jvm {
        sourceSets {
            named("jvmMain") {
                resources.srcDir("src/commonMain/resources") // <============= here
            }
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                // compose libraries
                implementation(compose.runtime)
                implementation(compose.foundation)
                @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
                implementation(compose.components.resources)
            }
        }
        
        val jvmMain by getting {
            dependencies {
                implementation(compose.desktop.currentOs)
            }
        }
    }
}

android {
    namespace = "a.b.c"
    compileSdk = 33
    defaultConfig {
        minSdk = 21
    }
    sourceSets {
        named("main") {
            manifest.srcFile("src/androidMain/AndroidManifest.xml")
            res.srcDirs("src/commonMain/resources") // <============= here
        }
    }
}

To get the fonts create a provider file inside :shared:commonMain/ as:

expect val acmeTypography: Typography

Now implement it inside both :shared:androidMain and :shared:jvmMain as:

// shared:jvmMain/

import androidx.compose.ui.text.platform.Font

actual val acmeTypography = Typography(
    defaultFontFamily = FontFamily(
        Font(resource = "font/acme_regular.ttf", FontWeight.Normal)
    ),
)

// shared:androidMain
import androidx.compose.ui.text.font.Font

actual val acmeTypography = Typography(
    defaultFontFamily = FontFamily(
        Font(R.font.acme_regular, FontWeight.Normal)
    ),
)
philoopher97
  • 772
  • 1
  • 6
  • 18
0

This is other way to link and use custom Compose fonts in Compose Multiplatform

https://jassielcastro.medium.com/custom-fonts-in-android-and-ios-applications-using-kotlin-multiplatform-and-jetpack-compose-c88d2d519e77