Mastering MaterialTheme Typography in Jetpack Compose: A Complete Guide

In Jetpack Compose, typography plays a pivotal role in defining the look and feel of your application. MaterialTheme provides a structured and customizable way to manage your app’s fonts, styles, and overall text appearance. Understanding how to leverage MaterialTheme.typography is essential for creating visually appealing and consistent UIs.

What is MaterialTheme Typography?

MaterialTheme.typography is a core component of the Material Design system in Jetpack Compose, offering a predefined set of text styles. These styles include h1 to h6 (for headings), body1, body2 (for main text), button, caption, and more. Each style provides a set of attributes such as font family, font weight, font size, and letter spacing. By utilizing these predefined styles, you can maintain consistency and ensure a polished look across your app.

Why Use MaterialTheme Typography?

  • Consistency: Ensures a consistent typographic style throughout your application.
  • Customization: Allows you to easily customize the typography to match your brand.
  • Theming: Supports dynamic theming for different modes (e.g., light and dark).
  • Readability: Promotes better readability and user experience by utilizing established text styles.

How to Implement MaterialTheme Typography in Jetpack Compose

To effectively implement MaterialTheme.typography, follow these steps:

Step 1: Understand the Default Typography Styles

Material Design provides a set of default typography styles which include:

  • displayLarge
  • displayMedium
  • displaySmall
  • headlineLarge
  • headlineMedium
  • headlineSmall
  • titleLarge
  • titleMedium
  • titleSmall
  • bodyLarge
  • bodyMedium
  • bodySmall
  • labelLarge
  • labelMedium
  • labelSmall

Step 2: Applying Typography Styles to Text

You can apply these styles directly to your Text composables using the style parameter:


import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun TypographyExample() {
    Text(
        text = "This is a headline",
        style = MaterialTheme.typography.headlineLarge
    )
    Text(
        text = "This is body text",
        style = MaterialTheme.typography.bodyMedium
    )
    Text(
        text = "This is a button",
        style = MaterialTheme.typography.labelLarge
    )
}

@Preview(showBackground = true)
@Composable
fun TypographyExamplePreview() {
    TypographyExample()
}

In this example:

  • The headlineLarge style is applied to the first Text composable, rendering it as a large headline.
  • The bodyMedium style is applied to the second Text composable, rendering it as the standard body text.
  • The labelLarge style is applied to the third Text composable, rendering it as a large label, suitable for buttons.

Step 3: Customizing Typography

To customize the typography, you can create a new Typography object with your desired font families, weights, and sizes. You need to also make sure to import the font files you intend to use.


import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import androidx.compose.ui.text.font.Font
import com.example.jetpackcompose.R  // Replace with your actual resource package
import androidx.compose.runtime.Composable

// Define custom font families
val customFontFamily = FontFamily(
    Font(R.font.raleway_regular, FontWeight.Normal), // Replace with your font resource
    Font(R.font.raleway_bold, FontWeight.Bold)   // Replace with your font resource
)

// Create a custom Typography object
val CustomTypography = Typography(
    headlineLarge = TextStyle(
        fontFamily = customFontFamily,
        fontWeight = FontWeight.Bold,
        fontSize = 32.sp
    ),
    bodyMedium = TextStyle(
        fontFamily = customFontFamily,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp
    ),
    labelLarge = TextStyle(
        fontFamily = customFontFamily,
        fontWeight = FontWeight.Bold,
        fontSize = 14.sp
    )
)


@Preview(showBackground = true)
@Composable
fun CustomTypographyExample() {
    // Applying the custom Typography
   androidx.compose.material3.MaterialTheme(typography = CustomTypography) {
        Text(
            text = "This is a custom headline",
            style = MaterialTheme.typography.headlineLarge
        )
        Text(
            text = "This is custom body text",
            style = MaterialTheme.typography.bodyMedium
        )
         Text(
            text = "This is a custom button",
            style = MaterialTheme.typography.labelLarge
        )
   }
}

In this code:

  • A custom font family, customFontFamily, is created using fonts loaded from resources. Make sure that the font files are included into the “`res/font“` directory.
  • A Typography object named CustomTypography is created, specifying the font family, weight, and size for various text styles.
  • These custom styles are then applied within the MaterialTheme to ensure they are used consistently throughout your composable.

Step 4: Theming Typography

To support different themes, such as light and dark modes, you can create separate typography configurations for each mode. Use isSystemInDarkTheme() to determine the current theme and apply the corresponding typography.


import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.Typography
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

@Composable
fun ThemedTypography() {
    val typography = if (isSystemInDarkTheme()) {
        // Define dark theme typography
        Typography(
            bodyLarge = TextStyle(
                fontFamily = FontFamily.Serif,
                fontWeight = FontWeight.Normal,
                fontSize = 16.sp,
                color = androidx.compose.ui.graphics.Color.White
            )
        )
    } else {
        // Define light theme typography
        Typography(
            bodyLarge = TextStyle(
                fontFamily = FontFamily.Serif,
                fontWeight = FontWeight.Normal,
                fontSize = 16.sp,
                color = androidx.compose.ui.graphics.Color.Black
            )
        )
    }

    MaterialTheme(typography = typography) {
        Text(
            text = "This text changes color based on the theme",
            style = MaterialTheme.typography.bodyLarge
        )
    }
}

@Preview(showBackground = true)
@Composable
fun ThemedTypographyPreview() {
    ThemedTypography()
}

Advanced Typography Customization

Using Custom Fonts

You can include custom fonts in your project and use them in your typography. First add font resources directory in “`res“` folder

Implementing Dynamic Type

Dynamic type allows users to adjust the text size in the settings and your application should respond to this. Use LocalDensity.current.fontScale to adjust the font sizes accordingly.


import androidx.compose.material3.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.sp

@Composable
fun DynamicTypeExample() {
    val fontScale = LocalDensity.current.fontScale

    val dynamicStyle = MaterialTheme.typography.bodyLarge.copy(
        fontSize = MaterialTheme.typography.bodyLarge.fontSize * fontScale
    )

    Text(
        text = "This is body text that scales with dynamic type settings",
        style = dynamicStyle
    )
}

@Preview(showBackground = true)
@Composable
fun DynamicTypeExamplePreview() {
    DynamicTypeExample()
}

Conclusion

Effectively using MaterialTheme.typography in Jetpack Compose is crucial for creating a visually appealing, consistent, and accessible user interface. By customizing and applying typography styles, you can enhance your app’s readability, reinforce your brand identity, and ensure a better user experience. Properly implementing typography also allows for better theming and accessibility support, leading to a polished and professional application.