Jetpack Compose - Typography

This example demonstrates how to make a Jetpack Compose Custom Font Family in Android 

I have downloaded fonts from https://fonts.google.com/, after that, I created a new directory named font under the res directory and copied fonts .ttf files inside it.

Note: You need to declare fonts with their respective font style and font-weight otherwise it can cause a runtime exception.

Type.kt

package io.material.compose.ui.theme

import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import io.material.compose.R


val jostFontFamily = FontFamily(
Font(R.font.jost_book, FontWeight.Normal),
Font(R.font.jost_book, FontWeight.Light),
Font(R.font.jost_book, FontWeight.Medium),
Font(R.font.jost_medium, FontWeight.SemiBold),
Font(R.font.jost_medium, FontWeight.Bold),
)

// Set of Material typography styles to start with
val Typography = Typography(

displayLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Light,
fontSize = 57.sp,
lineHeight = 64.sp,
letterSpacing = 0.sp
),
displayMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Light,
fontSize = 45.sp,
lineHeight = 52.sp,
letterSpacing = 0.sp
),
displaySmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 36.sp,
lineHeight = 44.sp,
letterSpacing = 0.sp
),
headlineLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 32.sp,
lineHeight = 40.sp,
letterSpacing = 0.sp
),
headlineMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 28.sp,
lineHeight = 36.sp,
letterSpacing = 0.sp
),
headlineSmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 32.sp,
letterSpacing = 0.sp
),
titleLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
titleMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
titleSmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
),
bodyLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
bodyMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
),
bodySmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.4.sp
),
labelLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
),
labelMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
),
labelSmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
)

Theme.kt

package io.material.compose.ui.theme


import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.ViewCompat


private val LightThemeColors = lightColorScheme(

primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
)
private val DarkThemeColors = darkColorScheme(

primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
)

@Composable
fun Material3ComposeTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {




val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkThemeColors
else -> LightThemeColors
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
(view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
}
}

MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

TypographyDemo.kt

package io.material.compose

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import io.material.compose.ui.design.*
import io.material.compose.ui.theme.Purple40


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TextFieldDemo(navController: NavController) {

Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("Text fields") },
Modifier.background(Purple40),
navigationIcon = {
IconButton(onClick = { /* doSomething() */
navController.navigateUp()
}) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Localized description"
)
}
},

/*actions = {
IconButton(onClick = { */
/* doSomething() *//* }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
}*/

)
},
content = {
Column(
modifier = Modifier
.padding(20.dp)
.verticalScroll(rememberScrollState())
) {

Text("Simple Text Field Sample",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
SimpleTextFieldSample()
ListDividerPadding()

Text("Simple Outlined Text Field Sample",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
SimpleOutlinedTextFieldSample()
ListDividerPadding()

Text("Text Field With Icons",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextFieldWithIcons()
ListDividerPadding()

Text("Text Field With Placeholder",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextFieldWithPlaceholder()
ListDividerPadding()

Text("Text Field With Error State",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextFieldWithErrorState()
ListDividerPadding()

Text("Text Field With Helper Message",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextFieldWithHelperMessage()
ListDividerPadding()

Text("Password Text Field",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
PasswordTextField()
ListDividerPadding()

Text("Text Field Sample",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextFieldSample()
ListDividerPadding()

Text("Outlined Text Field Sample",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
OutlinedTextFieldSample()
ListDividerPadding()

Text("Text Field With Hide Keyboard On Ime Action",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextFieldWithHideKeyboardOnImeAction()
ListDividerPadding()

Text("Text Area",
Modifier.padding(bottom = 10.dp),
style = MaterialTheme.typography.labelLarge)
TextArea()
ListDividerPadding()

}
}
)

}

..

Comments