Theme
is an experimental theme engine for Android by retinting views after their creation.
This library is inspired by aesthetic and Cyanea.
Theme
is a companion of material-components-android, so it requires you to adoptmaterial-components-android
in your project.- Currently,
Theme
only supportsmaterial-components-android
1.4.0. Any other version doesn't work. - Because the implementation is fragile, think twice, and do some investigation before using this library.
- Jetpack Compose supports theming programmatically and is a better alternative(in the future).
-
Install dependency:
-
Define six theme colors:
<resources> <color name="colorPrimary">#008577</color> <color name="colorPrimaryVariant">#00574B</color> <color name="colorOnPrimary">#FFFFFF</color> <color name="colorSecondary">#D81B60</color> <color name="colorSecondaryVariant">#A00037</color> <color name="colorOnSecondary">#FFFFFF</color> </resources>
- The color resources name must be identical to the names above.
- Color values must be formatted as
#RRGGBB
. Color references won't work because of howTypedArray.getResourceId
works.
-
Add an attribute to your root theme:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> ... <!-- Add this line --> <item name="viewInflaterClass">xyz.aprildown.theme.ThemeViewInflater</item> </style>
-
In your Application:
Theme.init( context = this, themeRes = R.style.AppTheme ) { // Optional. Provide initial colors here. // The usage is same as the code below. }
-
Change colors:
Theme.edit(this) { colorPrimaryRes = R.color.md_amber_500 colorPrimaryVariantRes = R.color.md_amber_800 colorOnPrimary = on(colorPrimary) colorSecondaryRes = R.color.md_blue_500 colorSecondaryVariantRes = R.color.md_blue_800 colorOnSecondary = on(colorSecondary) colorStatusBar = colorPrimaryVariant }
- Variables ending with
Res
expect aColorRes
. Other variables expect aColorInt
. - After editing, you have to recreate activities in the back stack manually.
- Variables ending with
-
[Optional] Use colors at runtime.
Theme.get().colorPrimary
Theme.tintSystemUi(activity)
- Put it in activity's
onCreate
, but if you're usingDrawerLayout
, put it afterDrawerLayout
is inflated(usually it's aftersetContentView
).
This's useful when you show a MaterialDatePicker
because Theme
messes up its colors.
button.setOnClickListener {
Theme.get().enabled = false
MaterialDatePicker.Builder.datePicker()
.build()
.apply {
addOnDismissListener {
Theme.get().enabled = true
}
}
.show(childFragmentManager, null)
}
-
Create a
ThemeInflationDelegate
like AppComponentsDelegate. -
Add it after
Theme
's initialization:Theme.init(...) Theme.installDelegates(AppComponentsDelegate())
- Style
Toolbar
according to the docs, or the tint doesn't work. Theme
doesn't use any reflection, so it's hard to tint widgets likeTimePicker
.
material-components-android
makes setting attributes programmatically very easy. ThemeViewInflater extends MaterialComponentsViewInflater and does all retint work. Classes named ***Tint
resolves color attributes from AttributeSet
and applies new color.