Jetpack compose get FontFamily from resources

Viewed 2960

In res/font I have defined font-family like this:

<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
    <font app:fontStyle="normal" app:fontWeight="400" app:font="xyz_1"/>
    <font app:fontStyle="normal" app:fontWeight="500" app:font="xyz_2"/>
</font-family>

How I can load this in Jetpack Compose and use it as FontFamily object?

4 Answers

Unfortunately there isn't yet a straightforward solution to load Font-Familys directly in compose from xml.

I'd consider the following options:

  1. Define the material design text styles (body1, body2, etc..) in xml for the theme and use MDC-theme adapter to migrate them to MaterialTheme.typography
  2. The above might not work for special font familys, for example a logo or other use-cases. In that case I'd go with recreating the FontFamily for compose:
private val appFontFamily = FontFamily(
   fonts = listOf(
       Font(
           resId = R.font.roboto_black, 
           weight = FontWeight.W900, 
           style = FontStyle.Normal
       ),
       Font(
           resId = R.font.roboto_black_italic, 
           weight = FontWeight.W900, 
           style = FontStyle.Italic
       ),
       Font(
           resId = R.font.roboto_bold, 
           weight = FontWeight.W700, 
           style = FontStyle.Normal
       ),
       ...
   )
)

Here is a good read about this: https://alexzh.com/jetpack-compose-theme-and-typography/. Also one could get inspired and contribute to the Mdc-theme adapter to cover these special use-cases that are outside of the theme as well. I suppose the logic of reading in text styles to compose is already there, one just needs to provide an API to read in custom ones, other than the ones specified in the Material Theme.

for any one who wants to change the app's font do the following

  1. Create font directory in res (res/font)

  2. copy your .ttf fonts in res/font

  3. find the Type.kt file ( in ui/theme directory )

  4. create a variable for font in Type.kt

    val MyCustomFont = FontFamily(
        Font(R.font.regular),
        Font(R.font.bold,FontWeight.Bold)
    )
    
  5. there is Typography val in Type.kt file, you can change the entire app's font family by putting defaultFontFamily = MyCustomFont in this val

    val Typography = Typography(
        defaultFontFamily = MyCustomFont,
        body1 = TextStyle(
            fontFamily = MyCustomFont2,
            fontWeight = FontWeight.Normal,
            fontSize = 16.sp
     ),
    
  6. you can also set font family to specific typography like body1, h1, h2, ...

val FontName = FontFamily(
    Font(R.font.font_reg, FontWeight.Normal),
    Font(R.font.font_light,FontWeight.Light),
    Font(R.font.font_sbold, FontWeight.SemiBold),
    Font(R.font.font_xbold, FontWeight.ExtraBold)
)

In any Kotlin file (outside class)

Then use in any composable:

@Composable
    fun FontStyledText(text: String) {
        Text(
            text = text,
            fontFamily = FontName,
            fontWeight = FontWeight.SemiBold
        )
    }
val QuickSand = FontFamily(
    Font(R.font.quicksand_light, weight = FontWeight.Light),
    Font(R.font.quicksand_regular, weight = FontWeight.Normal),
    Font(R.font.quicksand_medium, weight = FontWeight.Medium),
    Font(R.font.quicksand_semibold, weight = FontWeight.SemiBold),
    Font(R.font.quicksand_bold, weight = FontWeight.Bold)
)

// Set of Material typography styles to start with
val Typography = Typography(
    body1 = TextStyle(
        fontFamily = QuickSand,
        fontWeight = FontWeight.Light,
        fontSize = 16.sp,
    ),
    h1 = TextStyle(
        fontFamily = QuickSand,
        fontWeight = FontWeight.SemiBold,
        fontSize = 24.sp
    ),
    h2 = TextStyle(
        fontFamily = QuickSand,
        fontWeight = FontWeight.Bold,
        fontSize = 22.sp
    )
Related