
In this article, we will explore themes in Android Jetpack Compose and how to use colors, shapes, and typography with examples.
What is a Jetpack Compose Theme?
Themes provide a consistent look and feel to your app. They contain things like color and typography.
By default, Jetpack Compose follows material guidelines. So, all the composables (like Button, Textfield, etc.) are made from the Material Design specifications.
When you create a project, Android Studio adds a new package called ui.theme.

It contains 4 Kotlin files:
- Color.kt
- Shape.kt
- Type.kt
- Theme.kt
Let’s explore these 4 files.
Jetpack Compose Colors:
The Material Design System comes with default colors for customizing your app.
The system contains 4 types of colors:
- Primary and secondary colors
- Variants of primary and secondary colors
- Additional colors
- “On” Colors
1. Primary and Secondary Colors:
Primary color displayed most frequently across your app’s screens and components. Generally, it represents your brand.
Secondary color is optional. It provides more ways to accent and distinguishes your product. Generally, we use secondary color for floating action buttons, progress bars, highlighting selected text, etc…
2. Variants of Primary and Secondary Colors:
These are slightly different variations of the primary and secondary colors. For example, most of the apps apply the primary color to the top app bar and the primary variant to the status bar.
Example:

3. Additional Colors:
Surface, background, and error colors come under additional colors.
Surface colors affect the surfaces of components, such as cards, sheets, and menus.
The background color appears behind scrollable content. It is the background color of your app UI.
Error color indicates errors in components, such as invalid text in a text field.
4. “On” Colors:
“on” colors are applied to the elements (like text and icons) that appear “on” top of certain colors (like primary and secondary).
There are 5 “on” colors:
- On Primary
- On Secondary
- On Surface
- On Background
- On Error
“On Primary” color is applied to the elements that appear on the top of the primary color. Similarly, the “On Secondary” color is applied to the elements that appear on top of the secondary color, and so on.
You can learn more about Material Colors here.
In the Android Studio, the Color.kt file contains the colors used in the project. If you open it, you will find the default colors.

Let’s look at the Color() method. It takes hexadecimal number and returns the Color object.
Example:
val Purple200 = Color(0xFFBB86FC)
The number 0xFFBB86FC represents purple. It can be divided into three parts – 0x, FF, and BB86FC.
0x – It represents that this is a hexadecimal number.
FF – It represents transparency (alpha) in hex. 00 means 100% transparent and FF means 100% opaque.
BB86FC – This is the actual color code of the purple. You can find color codes using this tool.
Let’s add blue, pink, and red colors. The color codes are 0000FF, FF009E, and FF001E respectively.

Tip: There is a color button before each variable. If you click on it, you will see a color picker.

You can also select colors using the color picker.
Jetpack Compose Shapes:
In Material Design, the UI elements are divided into 3 categories based on their size.
- Small components (Button, TextField, etc.)
- Medium components (Card, Dialog, etc.)
- Large components (Modal bottom sheet, Navigation Drawer, etc.)
You can learn more about material shapes here.
In the Android Studio, open the Shape.kt file. You will find the following code.
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)
The Shapes class has small, medium, and large parameters. They are applied to the small, medium, and large components (UI elements) respectively.
Related: Rounded Corner Shape in Jetpack Compose
Jetpack Compose Fonts and Typography:
The Material Design System offers 13 different styles like H1, H2, subtitle1, body1, etc…
You can learn more about the type system here.
Open the Type.kt file.

In the code, the 13 styles are defined using the Typography class.
@Immutable
class Typography internal constructor(
val h1: TextStyle,
val h2: TextStyle,
val h3: TextStyle,
val h4: TextStyle,
val h5: TextStyle,
val h6: TextStyle,
val subtitle1: TextStyle,
val subtitle2: TextStyle,
val body1: TextStyle,
val body2: TextStyle,
val button: TextStyle,
val caption: TextStyle,
val overline: TextStyle
)
Each style is described by the TextStyle class. The class takes parameters like font color, size, weight, etc…
@Immutable
class TextStyle(
val color: Color = Color.Unspecified,
val fontSize: TextUnit = TextUnit.Unspecified,
val fontWeight: FontWeight? = null,
val fontStyle: FontStyle? = null,
val fontSynthesis: FontSynthesis? = null,
val fontFamily: FontFamily? = null,
val fontFeatureSettings: String? = null,
val letterSpacing: TextUnit = TextUnit.Unspecified,
val baselineShift: BaselineShift? = null,
val textGeometricTransform: TextGeometricTransform? = null,
val localeList: LocaleList? = null,
val background: Color = Color.Unspecified,
val textDecoration: TextDecoration? = null,
val shadow: Shadow? = null,
val textAlign: TextAlign? = null,
val textDirection: TextDirection? = null,
val lineHeight: TextUnit = TextUnit.Unspecified,
val textIndent: TextIndent? = null
)
We will define our custom text styles using these classes in a moment.
Jetpack Compose Theme File:
Open the Theme.kt file. You will find two functions:
darkColors() – For dark theme
lightColors() – For light/day theme

The functions have parameters like primary, primaryVariant, secondary, etc… These are the material colors we have seen in the Colors section above. We can override these values easily.
private val DarkColorPalette = darkColors(
primary = myColor1,
primaryVariant = myColor2,
secondary = Teal200,
// override other colors
background = Color.DarkGray,
surface = Color.Gray
)
private val LightColorPalette = lightColors(
primary = myColor1,
primaryVariant = Purple700,
secondary = Teal200,
// override other colors
background = Color.White,
surface = Color.White
)
If you scroll down, you will find a composable with your project name.

This is what you see in the MainActivity class.

The composable has 2 parameters:
darkTheme – To apply the dark theme or not.
content – This is the app UI we write in the MainActivity.
Inside the function, MaterialTheme() is called.
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
It applies the Material Design Principles to the content (app UI). We can set our own colors, typography, and shapes.
How to Use Theme Colors?
Material Theme has colors (like primary, secondary, and background) in Theme.kt file. We can easily access them in our code by using the MaterialTheme.colors property.
MaterialTheme.colors.primary // returns the primary color
MaterialTheme.colors.secondary // returns the secondary color
Example:
Column(
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colors.primary) // set primary color
) {
}
We can also directly use the colors we added in the Color.kt file.
Column(
modifier = Modifier
.fillMaxSize()
.background(color = Purple200)
) {
}
How to Use Theme Text Styles?
Similar to colors, we can access Material Theme text styles from MaterialTheme.typography property.
Text(
text = "SemicolonSpace",
style = MaterialTheme.typography.h1 // set h1 style
)
How to Override Material Theme Typography in Jetpack Compose?
It’s easy to override Material Theme text styles. First, download and add fonts to the Android Studio Project. For this article, I have added Poppins Font.

Next, open Type.kt and add your custom typography.
val MyFontFamily = FontFamily(
Font(R.font.poppins_bold,FontWeight.Bold),
Font(R.font.poppins_medium,FontWeight.Medium),
Font(R.font.poppins_regular,FontWeight.Normal)
)
val MyTypography = Typography(
h1 = TextStyle(
fontFamily = MyFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 20.sp
),
body1 = TextStyle(
fontFamily = MyFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
// similarly, override other parameters like h2, subtitle, etc...
)
Next, open Theme.kt file and look at the MaterialTheme() function. Change its typography parameter.
MaterialTheme(
colors = colors,
typography = MyTypography,
shapes = Shapes,
content = content
)
Now, apply the text style as we did above.
Text(
text = "SemicolonSpace H1",
style = MaterialTheme.typography.h1
)
Text(
text = "SemicolonSpace Body1",
style = MaterialTheme.typography.body1
)
How to Add a New Custom Typography in Jetpack Compose?
Instead of overriding the Material Theme, we can also add new custom typography using Kotlin extension functions.
In the Type.kt file, add the following code.
val MyFontFamily = FontFamily(
Font(R.font.poppins_bold, FontWeight.Bold),
Font(R.font.poppins_medium, FontWeight.Medium),
Font(R.font.poppins_regular, FontWeight.Normal)
)
val MaterialTheme.myTypography: Typography
@Composable
get() {
return Typography(
h1 = TextStyle(
fontFamily = MyFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 20.sp
),
body1 = TextStyle(
fontFamily = MyFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
// similarly, override other parameters like h2, subtitle, etc...
)
}
Note: You can add the code wherever you want. But for project maintenance, include it in the corresponding file.
In the code, you can access the styles like this:
Text(
text = "SemicolonSpace H1",
style = MaterialTheme.myTypography.h1 // apply h1 style
)
You can also directly apply styles:
Text(
text = "SemicolonSpace",
style = TextStyle(
fontFamily = FontFamily(Font(R.font.poppins_bold, FontWeight.Bold)),
fontWeight = FontWeight.Bold,
fontSize = 30.sp
)
)
This is all about Jetpack Compose Themes. I hope you have learned something new. If you have any doubts, comment below.
Related:
- Jetpack Compose Scaffold with Example
- How to Check Internet Connection in Android Programmatically?
- 5 Awesome Jetpack Compose Loading Animations with Source Code
References: