Using Custom Fonts in KMP (Compose Multiplatform)
Hi all the KMP developers.
Well, do you want to use fonts in your Compose Multiplatform Project?
Let’s Skip the shit and let's see how it's done.
Let’s Start with downloading the fonts here.
Here I have downloaded Montserrat Alternates
Now add them to your commonMain/resources/font directory and change the names as they should not contain capitals and spaces.
Not enable resource support by adding the following experimental library dependency. Note that it requires you to opt in for usage.
commonMain.dependencies {
// other common dependencies
@OptIn(ExperimentalComposeLibrary::class)
implementation(compose.components.resources)
}
After that make sure you add the common resources to your Android source sets. This has been the issue for Compose Multiplatform's latest version hope it gets fixed
android {
sourceSets["main"].res.srcDirs("src/commonMain/resources", "src/androidMain/res")
sourceSets["main"].resources.srcDirs("src/commonMain/resources")
}
Now let's start the actual work
Create an expect composable function that will take a string or resource name and return a Font
@Composable
expect fun font(
name: String,
res: String,
weight: FontWeight,
style: FontStyle
): Font
Now add your actual definitions for different sources as shown
Android
@Composable
actual fun font(
name: String,
res: String,
weight: FontWeight,
style: FontStyle
): Font {
val context = LocalContext.current
val id = context.resources.getIdentifier(res, "font", context.packageName)
return Font(id, weight, style)
}
IOS
private val cache: MutableMap<String, Font> = mutableMapOf()
@OptIn(ExperimentalResourceApi::class)
@Composable
actual fun font(
name: String,
res: String,
weight: FontWeight,
style: FontStyle
): Font {
return cache.getOrPut(res) {
val byteArray = runBlocking {
resource("font/$res.ttf").readBytes()
}
Font(res, byteArray, weight, style)
}
}
Desktop
@Composable
actual fun font(
name: String,
res: String,
weight: FontWeight,
style: FontStyle
): Font = Font("font/$res.ttf", weight, style)
Note for IOS and Desktop you have to add the platform Font import
import androidx.compose.ui.text.platform.Font
Now let’s see how to use them in our Material Theme like we generally do in Android
@Composable
fun getTypography(): Typography {
val Montserrat = FontFamily(
font(
name = "Mons Bold",
res = "mons_bold",
weight = FontWeight.Bold,
style = FontStyle.Normal
),
font(
name = "Mons Semibold",
res = "mons_semibold",
weight = FontWeight.SemiBold,
style = FontStyle.Normal
)
)
return Typography(
h1 = TextStyle(
fontFamily = Montserrat,
fontSize = 38.sp,
fontWeight = FontWeight.Bold,
),
body1 = TextStyle(
fontFamily = Montserrat,
fontSize = 14.sp,
fontWeight = FontWeight.Normal,
)
)
This will be your Typo.kt file in your themes
@Composable
fun MyAppTheme(
content: @Composable () -> Unit,
) {
MaterialTheme(
colors = myColors,
content = content,
typography = getTypography()
)
}
And this is how you can use it in your theme or you can directly use the Style in your composables.
Hope this article helped you with using custom fonts easily without hassle in your Kotlin Multiplatform Application
Checkout Kashif Mehmood’s https://github.com/Kashif-E/KMPMovies for clear implementation
Update — The compose multi-platform resource Library has been updated and it’s really easy to use and you can use fonts easily.
If you like this a clap would mean a lot :)