Skip to content
Android theme concatenation via gradle plugin
Branch: develop
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci
.idea
demo
gradle/wrapper
themr
.gitignore
LICENSE
README.md
build.gradle
gradlew
gradlew.bat
settings.gradle

README.md

themr CircleCI Download

Theme concatenation via gradle plugin

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "com.github.ouchadam.themr:<latest-version>"
  }
}

apply plugin: 'com.android.application'
apply plugin: 'com.github.ouchadam.themr'

Usage

res/values/themr.xml

<style name="PaletteLight">
  <item name="brandColor">#008577</item>
</style>

<style name="PaletteDark">
  <item name="brandColor">#000000</item>
</style>

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="colorPrimary">?attr/brandColor</item>
</style>

build.gradle

themr {
  combinations = ["AppTheme": ["PaletteLight", "PaletteDark"]]
}
override fun onCreate(savedInstanceState: Bundle?) {
  setTheme(themr(R.style.PaletteDark, R.style.AppTheme))
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
}

private fun Activity.themr(paletteId: Int, themeId: Int): Int {
  val paletteStyle = this.resources.getResourceName(paletteId).split("/")[1]
  val themeStyle = this.resources.getResourceName(themeId).split("/")[1]
  return this.resources.getIdentifier(paletteStyle + "_" + themeStyle, "style", this.packageName)
}

What is this?

A gradle plugin to generate combinations of themes based on a color palette. This is done by simplying inlining a palette style into a theme style.

The example above will generate

<style name="PaletteLight_AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="brandColor">#008577</item>
  <item name="colorPrimary">?attr/brandColor</item>
</style>

<style name="PaletteDark_AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="brandColor">#000000</item>
  <item name="colorPrimary">?attr/brandColor</item>
</style>

Why is this useful?

When an app uses mulitple themes

<style name="HomeTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/blue</item>
    <item name="android:textColor">@color/black</item>
</style>

<style name="DetailsTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/red</item>
    <item name="android:textColor">@color/white</item>
</style>

and different palettes are required such as a dark mode, management starts to get tricky, especially when more palettes are introduced. This can be achieved by copying all of the themes for each palette, rearchitecting the theme hierarchy or by programatically applying the colours.

<style name="HomeTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/blue</item>
    <item name="android:textColor">@color/black</item>
</style>

<style name="DarkHomeTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/dark_blue</item>
    <item name="android:textColor">@color/grey</item>
</style>
fun bindView(view) {
  val themeWrapper = createThemeWrapperFor(Configuration.DARK_MODE) // find all the dark mode attributes
  view.text.setTextColor(themeWrapper.colorPrimary)
}

themr reduces the need for this boiler plate by allowing the palettes and themes to be decoupled and the combinations auto generated.

Combinations are declared as part of the plugin extension

themr {
  combinations = [
    "HomeTheme": ["LightMode", "DarkMode"],
    "DetailsTheme": ["LightMode", "DarkMode"]
  ]
}
<style name="LightMode">
    <item name="brandColor">@color/blue</item>
    <item name="brandColorSecondary">@color/red</item>
    <item name="brandTextColor">@color/black</item>
    <item name="brandTextColorInverse">@color/white</item>
</style>

<style name="DarkMode">
    <item name="brandColor">@color/dark_blue</item>
    <item name="brandColorSecondary">@color/blue</item>
    <item name="brandTextColor">@color/grey</item>
    <item name="brandTextColorInverse">@color/black</item>
</style>

<style name="HomeTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">?attr/brandColor</item>
    <item name="android:textColor">?attr/brandTextColor</item>
</style>

<style name="DetailsTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">?attr/brandColorSecondary</item>
    <item name="android:textColor">?attr/brandTextColorInverse</item>
</style>

themr will generate styles to buildDir/generated/res/themer which the app can then consume via id or by resources.getIdentifier

{Palette}_{Theme}
LightMode_HomeTheme
DarkMode_HomeTheme
LightMode_DetailsTheme
DarkMode_DetailsTheme
You can’t perform that action at this time.