Introduction:
In the world of Android development, Jetpack Compose has revolutionized how we build user interfaces, offering a modern, declarative approach to UI design. One of the key elements in creating visually appealing and cohesive apps is the effective use of color, and with Material3, Google’s latest design system, you have a powerful set of tools to define and manage theme colors in your app.
Material3 brings a refined color system that enables developers to create adaptable and consistent color schemes across various components of their apps. Understanding how to leverage these colors within Jetpack Compose is crucial for building interfaces that not only look great but also provide a seamless user experience.
In this guide, we’ll dive into the details of Material3 theme colors, exploring each color’s role within a theme. We’ll also demonstrate how these colors affect UI elements in Jetpack Compose, ensuring that your app’s design remains consistent and visually engaging, whether you explicitly define colors or rely on Material3’s smart defaults.
Let’s define a color theme for our demo. We can use the following snippet as a foundation for exploring Material3 theme colors in Jetpack Compose.
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
private val LightColorScheme = lightColorScheme(
primary = Color(0xFF6200EE),
onPrimary = Color.White,
primaryContainer = Color(0xFF3700B3),
onPrimaryContainer = Color.White,
secondary = Color(0xFF03DAC6),
onSecondary = Color.Black,
secondaryContainer = Color(0xFF018786),
onSecondaryContainer = Color.Black,
tertiary = Color(0xFFB00020),
onTertiary = Color.White,
tertiaryContainer = Color(0xFF370617),
onTertiaryContainer = Color.White,
background = Color(0xFFFFFFFF),
onBackground = Color.Black,
surface = Color(0xFFFFFFFF),
onSurface = Color.Black,
error = Color(0xFFB00020),
onError = Color.White,
errorContainer = Color(0xFFFFDAD4),
onErrorContainer = Color.Black
)
private val DarkColorScheme = darkColorScheme(
primary = Color(0xFFBB86FC),
onPrimary = Color.Black,
primaryContainer = Color(0xFF6200EE),
onPrimaryContainer = Color.White,
secondary = Color(0xFF03DAC6),
onSecondary = Color.Black,
secondaryContainer = Color(0xFF03DAC5),
onSecondaryContainer = Color.Black,
tertiary = Color(0xFFCF6679),
onTertiary = Color.Black,
tertiaryContainer = Color(0xFFB00020),
onTertiaryContainer = Color.White,
background = Color(0xFF121212),
onBackground = Color.White,
surface = Color(0xFF121212),
onSurface = Color.White,
error = Color(0xFFCF6679),
onError = Color.Black,
errorContainer = Color(0xFFB00020),
onErrorContainer = Color.White
)
@Composable
fun MyAppTheme(
darkTheme: Boolean = false,
content: @Composable () -> Unit
) {
val colors = if (darkTheme) DarkColorScheme else LightColorScheme
MaterialTheme(
colorScheme = colors,
typography = Typography,
content = content
)
}
Explanation of Material3 Theme Colors
Before we explore each color in detail, it’s important to understand how colors are applied in your UI components when using Material3’s theming system.
Default Behavior of Theme Colors
In the examples below, I’ll show how different colors are used in the context of various UI elements. If you do not explicitly specify the color
or colors
parameters in your UI components (like Button
, Text
, etc.), the colors will automatically be drawn from the MaterialTheme.colorScheme
that you’ve defined for your app.
This means:
- Buttons: If you don’t specify a
colors
parameter for aButton
, it will use theprimary
color from your theme for its background and theonPrimary
color for its text by default. - Text: If you don’t specify a
color
parameter forText
inside a button or other elements, it will use the appropriateonColor
(likeonPrimary
,onSecondary
, etc.) based on the background color of the element.
In essence, unless you override them, the colors defined in your theme (e.g., primary
, onPrimary
, secondary
, etc.) will be automatically applied to ensure consistency across your UI. This automatic application of colors helps maintain a cohesive and visually appealing design without the need for repetitive color definitions.
Primary Color
Definition: The primary color is the main color used throughout your app to represent your brand or the dominant theme.
Role in the UI: This color is applied to major components like the app bar, primary buttons, and FABs. It helps create a consistent and recognizable user experience.
Example in Code:
— In the light color scheme: `primary = Color(0xFF6200EE)` is a shade of purple.
— In the dark color scheme: `primary = Color(0xFFBB86FC)` is a lighter shade of purple.
Primary UI Elements:
— App Bar: The app bar typically uses the primary color to create a strong visual identity.
— Primary Button: Buttons for key actions like “Submit” or “Save” often use the primary color.
Button(onClick = { /* do something */ }, colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.primary)) {
Text("Primary Button", color = MaterialTheme.colorScheme.onPrimary)
}
OnPrimary Color
Definition: The `onPrimary` color is used for any content (such as text or icons) that is placed on top of a surface colored with the `primary` color.
Example in Code:
— In the light theme: `onPrimary = Color.White` means any content on a primary-colored background will be white.
— In the dark theme: `onPrimary = Color.Black` ensures high contrast for readability on primary-colored elements.
UI Elements:
— Text on Primary Button: The text color on a button that uses the primary color is defined by the `onPrimary` color to maintain readability.
Button(onClick = { /* do something */ }, colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.primary)) {
Text("Click Me", color = MaterialTheme.colorScheme.onPrimary)
}
Job Offers
Secondary Color
Definition: The secondary color is used to provide accents to your primary color. It is often used for secondary actions and helps to create a visual contrast in the UI.
Role in the UI: This color is applied to components like secondary buttons or text fields to distinguish them from primary actions.
Example in Code
— In the light theme: `secondary = Color(0xFF03DAC6)` is a teal color.
— In the dark theme: `secondary = Color(0xFF03DAC6)` remains the same for consistency.
Button(onClick = { /* do something */ }, colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.secondary)) {
Text("Secondary Button", color = MaterialTheme.colorScheme.onSecondary)
}
OnSecondary Color
– Definition: `onSecondary` is used for text and icons placed on a surface colored with the `secondary` color.
– Example in Code:
— In both light and dark themes: `onSecondary = Color.Black` ensures that text and icons remain legible on secondary-colored backgrounds.
Usage Example in Compose:
Button(onClick = { /* do something */ }, colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.secondary)) {
Text("Secondary Action", color = MaterialTheme.colorScheme.onSecondary)
}
Tertiary Color
Definition: The tertiary color provides additional flexibility by offering another accent color to use across your UI. It can be used sparingly for highlighting elements or specialized cases.
Role in the UI: Used for tertiary actions, badges, or notifications that need to stand out but not overpower primary or secondary actions.
Example in Code:
— In the light theme: `tertiary = Color(0xFFB00020)` is a dark red color.
— In the dark theme: `tertiary = Color(0xFFCF6679)` is a softer pinkish-red tone.
Usage Example in Compose:
Text(
"Tertiary Color Text",
color = MaterialTheme.colorScheme.tertiary
)
Surface Color
– Definition: Surface colors are used for the background of UI components like cards, menus, and sheets.
– Role in the UI: Provides a consistent background color for surfaces on which content or actions appear.
– Example in Code:
— In the light theme: `surface = Color(0xFFFFFFFF)` (white).
— In the dark theme: `surface = Color(0xFF121212)` (dark gray).
Usage Example in Compose:
Surface(color = MaterialTheme.colorScheme.surface) {
Text("Surface Example", color = MaterialTheme.colorScheme.onSurface)
}
OnSurface Color
Definition: `onSurface` is used for any content (such as text or icons) that appears on top of a surface color.
Example in Code:
— In the light theme: `onSurface = Color.Black` for high contrast on white surfaces.
— In the dark theme: `onSurface = Color.White` for visibility on dark surfaces.
Background Color
– Definition: The background color is used for large UI areas, such as the overall background of the app.
– Role in the UI: Sets the overall look and feel of the app by defining the color of large areas.
– Example in Code:
— In the light theme: `background = Color(0xFFFFFFFF)` (white).
— In the dark theme: `background = Color(0xFF121212)` (dark gray).
OnBackground Color
– Definition: `onBackground` is used for text and icons placed on top of the background color.
– Example in Code:
— In the light theme: `onBackground = Color.Black`.
— In the dark theme: `onBackground = Color.White`.
Error Color
– Definition: The error color is used to signal problems or actions that require user attention.
– Example in Code**:
— In the light theme: `error = Color(0xFFB00020)` (red).
— In the dark theme: `error = Color(0xFFCF6679)` (pinkish-red).
OnError Color
- Definition: `onError` is used for content (such as text or icons) placed on top of the error color.
– Example in Code:
— In the light theme: `onError = Color.White`.
— In the dark theme: `onError = Color.Black`.
Conclusion:
Mastering Material3 theme colors in Jetpack Compose is key to creating visually consistent and accessible Android apps. By understanding and applying primary, secondary, and other theme colors, you can enhance the look and feel of your UI while ensuring usability across different themes.
Whether you’re explicitly setting colors or relying on Material3’s defaults, this guide has provided you with the tools to design a cohesive color scheme in your Compose applications. Thoughtful color use not only boosts your app’s aesthetic but also improves the overall user experience. Happy coding!
Dobri Kostadinov
Android Consultant | Trainer
Email me | Follow me on LinkedIn | Follow me on Medium | Buy me a coffee
This article is previously published by proandroiddev.com