Skip to content

Instantly share code, notes, and snippets.

@sababado
Created April 20, 2022 21:06
Show Gist options
  • Save sababado/eb5dbcc7ed41877bfd09dbd6c9a0c850 to your computer and use it in GitHub Desktop.
Save sababado/eb5dbcc7ed41877bfd09dbd6c9a0c850 to your computer and use it in GitHub Desktop.
Blog Template for Theming with Jetpack Compose

Composable UI

Composable UI is themed by default with a MaterialTheme object. It consists of three primary parts:

  1. Color
  2. Typography
  3. Shapes Each of these has a pre-defined structure that, when used properly, will make theming, branding, and non-functional UI changes a breeze. The intent is to encourage use of a small, consistent set of styles to make things more maintainable. Here are some considerations if your theme does not include a baseline purple color scheme, Roboto type scale, and slightly rounded shapes. Google provides an interactive codelab for anyone interested in getting a bit of practice. This codelab does not teach Jetpack Compose, but rather highlights organization and best practices of themes. Below are some high points. All Jetpack Compose lessons are here.

Organization

Some best practices and rules for the road:

  • Keep all theme files in a theme package. For example, com.sababado.ui.theme. This keeps everything organized as if it were kept in the res directory.

Color

The Material Color Tool can help identify a basic color scheme.

  • Color definitions belong in a theme.Color file.
  • Use "litaral" color names rather than "semantic" colors, as these may be used in multiple places. For example Red700 vs Primary. Red and LightishRed may be okay.
  • Automatically set a high / medium / none alpha on text based on heirarchy (top to bottom) using the CompositionLocalProvider.
  • By default: in light mode, primary colors are used to color a container, whereas in dark mode the surface color is used. The primarySurface color in light mode can also be used explicitely on a surface (like a TopAppBar) to make it more clear. In other words… color a surface with the primarySurface color. The color pallete provided:
Colors(
primary: Color?,
primaryVariant: Color?,
secondary: Color?,
secondaryVariant: Color?,
background: Color?,
surface: Color?,
error: Color?,
onPrimary: Color?,
onSecondary: Color?,
onBackground: Color?,
onSurface: Color?,
onError: Color?,
isLight: Boolean?
)

Details on each individual color.

Color Antipatterns

Don't use raw colors in files and classes

Surface(color = Color.LightGray) {
Text(
text = "Hard coded colors don't respond to theme changes :(",
textColor = Color(0xffff00ff)
)
}

Always reference a color by the theme. For example:

Surface(color = MaterialTheme.colors.primary)

Colors can be copied in specific places if needed, but should always be based on a theme color.

val derivedColor = MaterialTheme.colors.onSurface.copy(alpha = 0.1f)

Notice that the MaterialTheme colors class and variables are referenced everywhere in code. Once a custom theme is set, it overrides these variables. This is why it's extra important to stick to theming.

Typography

At the time of writing (Feb 2022), Jetpack Compose does not support pulling directly from Android's Downloadable Fonts. The Type Scale Tool can help generate code for specific fonts.

  • Any custom fonts used will have to be saved to the res/font directory and can be loaded in. The type system is similar to what can be found on most text editors (like MS Word). Some of the basic configurations include:
  • Scale Category (header1, body, button, subtitle, caption, etc)
  • ypeface
  • Weight
  • Size
  • Case
  • Letter spacing
  • And more! Today, the font should be created in a theme.Type or theme.Typography file and referenced in the theme. Text styles can be referenced the same way as colors.

Shapes

Use the Shape Customization Tool to help visualize corner and radius changes on various UI examples. Shapes are based on rounded corners or cut corners. Shape styles can be refereced from the MaterialTheme object just like colors and typography.

Styles

In xml based Android UI, styles can be extracted an reused in various components and UI elements without much restriction. This can lead to a disorganized mess of one-off and just barely slightly unique styles that offer little-to-no gain. And so, compose does not offer an explicit way to extract styles like Android View styles or css styles. Everything is written in Kotlin and the best way to achieve the same goal is to create a library of customized components to be used throught the app. For example a Header style to be used anywhere a header is needed. Colors, typography, and shapes are the building blocks to these components.

Theme

This is where it all comes together. Colors, typography, and shapes help define a theme and build it's various components.

  • Each theme should be in a Theme.kt file, and override what it needs to be different from Material.
  • Define the lists lightColors and darkColors here. These are theme specific lists of colors and should not be placed with the rest of the individual colors.
  • Custom themes are not referenced throughout the app. Instead, once a custom theme is set, the MaterialTheme objects are referenced to customize UI as needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment