Define theme in json file and dynamically load in to a ThemeModel and bind it to your views with DataBinding
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}dependencies {
implementation 'com.github.manneohlund:themeux:3.2.0'
}Create a class with any name and assign variables with key annotations to map preferred ui component to style.
You can pretty much build a ThemeModel with any attribute naming and set proper target annotation.
Colors can either be hex or as integer.
You can specify your own theme in styles and reference it via the package R.style.
Some annotations below are mandatory!
class ThemeModel {
@Theme
val theme = android.support.v7.appcompat.R.style.Theme_AppCompat_NoActionBar
@ToolbarThemeOverlay
val toolbarThemeOverlay = android.support.v7.appcompat.R.style.ThemeOverlay_AppCompat_Dark_ActionBar
@ToolbarPopupThemeOverlay
val popupThemeOverlay = android.support.v7.appcompat.R.style.ThemeOverlay_AppCompat_Dark
@AccentColor
val accentColor = Color.parseColor("#8BC34A")
@TaskDescriptionColor
@StatusBarColor
@PrimaryColor
val primaryColor = Color.parseColor("#4CAF50")
@NavigationBarColor
@PrimaryDarkColor
val primaryDarkColor = Color.parseColor("#C8388E3C")
}class ThemeModel {
@Theme
var theme = android.support.v7.appcompat.R.style.Theme_AppCompat_NoActionBar
@StatusBar
var statusBarColor = "#FFFF5722" // String or int color
@NavigationBar
var navigationBarColor = "#FFFF5722"
@ToolbarBar
var toolbarColor: String = "#FFFF5722"
@AccentColor
var accentColor: String = "#FFFF5722"
// Other colors
@PrimaryColor
var primaryColor: String = "#FFFF5722"
}Themeux will set a DefaultThemeLayoutInflaterFactory that will handle the theme/style setting on all android.support components for accentColor.
override fun onCreate(savedInstanceState: Bundle?) {
// Must be setup before onCreate to enable the json theme
val theme = Themeux.setup(this, ThemeModel::class)
// Call super after the JsonThemer setup
super.onCreate(savedInstanceState)
...
}Let the DataBinding in Android do the stitching.
Set the data model variable in your layout and bind model attributes in xml code ex: android:background="@{themeModel.primaryColor}".
// R.layout.activity_main
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="themeModel"
type="com.somepackage.model.ThemeModel" />
</data>
<!-- Layouts -->
<android.support.v7.widget.SomeView
...
android:background="@{themeModel.primaryColor}" />
</layout>override fun onCreate(savedInstanceState: Bundle?) {
// Must be setup before onCreate to enable the json theme
val theme = Themeux.setup(this, ThemeModel::class)
// Call super after the JsonThemer setup
super.onCreate(savedInstanceState)
// Setup data binding and set the theme and make custom changes to the layout
var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.themeModel = theme
// Set ActionBar from bindings
setSupportActionBar(binding.toolbar)
}Define themes in .json files and add it to assets folder, load them with your ThemeModel to override variables with the json theme variables.
// blue_theme.json
{
"theme": 0,
"toolbarThemeOverlay": 1,
"popupThemeOverlay": 0,
"statusBarColor": "#303F9F",
"toolbarColor": "#C83F51B5",
"accentColor": "#448AFF",
"navigationBarColor": "#C8303F9F",
"backgroundColor": "#FFFFFFFF"
}Note that annotations can be put on functions also! See @Theme @ToolbarThemeOverlay
class ThemeModel {
val LIGHT = 0
val DARK = 1
var theme = LIGHT
@StatusBar
var statusBarColor = "#FFFF5722"
@NavigationBar
var navigationBarColor = "#FFFF5722"
@ToolbarBar
val toolbarColor = "#FFFF5722"
@AccentColor
val accentColor = "#FFFF5722"
// Theme overlays
private var toolbarThemeOverlay: Int = LIGHT
private var popupThemeOverlay: Int = LIGHT
// Other
var windowBackgroundColor: String = "#FF000000"
@Theme
fun getModelTheme(): Int {
return when (theme) {
DARK -> return android.support.v7.appcompat.R.style.Theme_AppCompat_NoActionBar
else -> android.support.v7.appcompat.R.style.Theme_AppCompat_Light_NoActionBar
}
}
@ToolbarThemeOverlay
fun getToolbarThemeOverlay(): Int {
return when (toolbarThemeOverlay) {
DARK -> return android.support.v7.appcompat.R.style.ThemeOverlay_AppCompat_Dark_ActionBar
else -> android.support.v7.appcompat.R.style.ThemeOverlay_AppCompat_ActionBar
}
}
}override fun onCreate(savedInstanceState: Bundle?) {
// Load json theme and override target model
val theme: ThemeModel = let {
try {
Themeux.setup(this, "blue_theme.json")
} catch (e: Exception) {
Log.e(MainActivity::class.simpleName, "Error: AssetFileNotFound, " \+ e.message)
// Fallback on base model
ThemeModel()
}
}
// Call super after the JsonThemer setup
super.onCreate(savedInstanceState)
// Setup data binding and set the theme and make custom changes to the layout
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.themeModel = theme
// Set ActionBar from bindings
setSupportActionBar(binding.toolbar)
}