Compose walk-through part 3: Theming and Styling

Theming and styling are crucial in creating visually appealing and cohesive user interfaces. In Jetpack Compose, achieving a personalized and consistent look for your app involves customizing the MaterialTheme most of the time. Let's explore how to tailor themes, including dark and light themes, typography, and colors.

Defining a Custom MaterialTheme

To define a custom MaterialTheme, use the MaterialTheme composable and configure its properties to suit your app's aesthetics.

fun MyCustomTheme(content: @Composable (PaddingValues) -> Unit) {
  MaterialTheme(
    typography = MyTypography, // Custom typography
    colors = MyColorPalette,   // Custom color palette
    content = content
  )
}

val MyTypography = Typography(
  defaultFontFamily = FontFamily.Serif,
  h1 = TextStyle(
    fontFamily = FontFamily.SansSerif,
    fontWeight = FontWeight.Bold,
    fontSize = 30.sp
  ),
)

val MyColorPalette = lightColors(
  primary = Color.Red,
  secondary = Color.Green,
  background = Color.White,
)

In this example, MyCustomTheme is a wrapper around MaterialTheme, allowing you to specify custom typography and colors.

Dark and Light Themes

Jetpack Compose simplifies the process of implementing dark and light themes. You can define your custom color palettes for both themes and apply them accordingly.

val LightColorPalette = lightColors(
  primary = Color.Blue,
  secondary = Color.Yellow,
  background = Color.White
)

val DarkColorPalette = darkColors(
  primary = Color.Cyan,
  secondary = Color.Magenta,
  background = Color.Black
)

@Composable
fun MyApp() {
MaterialTheme(
  colors = if (isSystemInDarkTheme()) 
    DarkColorPalette else LightColorPalette
  ) {
     // Your app content
  }
}

Here, the app adapts to the system's theme, switching between light and dark color palettes.

Overriding Defaults

Customizing specific components within your theme is straightforward. For example, changing the color of a TextField is as simple as modifying its colors property.

TextField(
  value = text,
  onValueChange = { newText -> text = newText },
    label = { Text("Enter text") },
    colors = TextFieldDefaults.textFieldColors(
      textColor = Color.Gray,
      backgroundColor = Color.LightGray,
      focusedIndicatorColor = Color.Transparent,
      unfocusedIndicatorColor = Color.Transparent
  )
)

In this example, we customize the colors of the TextField to fit a specific design.

Typography Adjustments

Customizing text styles can be achieved by modifying the Typography property in your theme.

val MyCustomTypography = Typography(
  defaultFontFamily = FontFamily.SansSerif,
    h1 = TextStyle(
    fontWeight = FontWeight.Bold,
    fontSize = 30.sp,
    color = Color.Black
  ),
  body1 = TextStyle(
    fontSize = 16.sp,
    lineHeight = 24.sp,
    color = Color.Gray
  )
)

@Composable
fun MyThemedApp() {
  MaterialTheme(
    typography = MyCustomTypography
  ) {
    // Your app content
  }
}

These adjustments provide fine-grained control over the text appearance throughout your application.

By understanding how to customize the MaterialTheme, you can craft a unique and visually consistent experience for your users. Experiment with colors, typography, and other theme properties to achieve your Jetpack Compose app's desired look and feel.

Until the next one, happy coding!


Compose walk-through part 1: Basic components
Uncover Jetpack Compose in this series. Let’s start with key elements like Columns, Rows, Text, Buttons, Spacers, and Surfaces. Master these building blocks for dynamic UIs, and extend your Android skills to multiple platforms.
Compose walk-through part 2: Managing state
Understanding how the state works in Compose is essential for creating applications that respond dynamically to user input and data changes.