Theme
🎨 An Experimental Theme Engine for Android
Install / Use
/learn @DeweyReed/ThemeREADME
[Experimental] Theme
<img src="images/image.gif" alt="image" title="image" width="300" align="right" />Theme is an experimental theme engine for Android by retinting views after their creation.
This library is inspired by aesthetic and Cyanea.
WARNING
Themeis a companion of material-components-android, so it requires you to adoptmaterial-components-androidin your project.- Currently,
Themeonly supportsmaterial-components-android1.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).
Sample App
Usage
-
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.getResourceIdworks.
-
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
Resexpect 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
More Settings
Tint Status Bar and Navigation Bar
Theme.tintSystemUi(activity)
- Put it in activity's
onCreate, but if you're usingDrawerLayout, put it afterDrawerLayoutis inflated(usually it's aftersetContentView).
Disable Theme
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)
}
Support Custom Views
-
Create a
ThemeInflationDelegatelike AppComponentsDelegate. -
Add it after
Theme's initialization:Theme.init(...) Theme.installDelegates(AppComponentsDelegate())
Limitation
- Style
Toolbaraccording to the docs, or the tint doesn't work. Themedoesn't use any reflection, so it's hard to tint widgets likeTimePicker.
How Theme Works
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.
License
Related Skills
node-connect
348.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
108.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
348.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
348.0kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
