Long story short, I have an app in which I applied style attributes directly on activities and fragment's XML files. And now I am refactoring that into a styles.xml
file. I barely dare to mess with modifying the theme itself directly, because I already tried something similar before and inheritance became chaos.
So, I have several styles like this in my styles.xml
file:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<style name="My_DarkMode" parent="Theme.MyApp">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
</style>
<style name="My_DarkMode.MaterialToolbar">
<item name="android:background">@color/purple_500</item>
</style>
<style name="My_DarkMode.TextView">
<item name="android:textColor">@color/white</item>
</style>
<style name="My_DarkMode.HighlightedText">
<item name="android:textColor">@color/yellow_4text</item>
</style>
<style name="My_DarkMode.TabLayout">
<item name="android:background">@color/tab_grey</item>
<item name="tabIndicatorColor">@color/tab_indicator</item>
<item name="tabSelectedTextColor">@color/tab_selected_text</item>
<item name="tabTextColor">@color/tab_text</item>
</style>
<style name="My_DarkMode.FragmentBg">
<item name="android:background">@color/black</item>
</style>
<style name="My_DarkMode.MainBg">
<item name="android:background">@color/activity_grey</item>
</style>
<style name="My_DarkMode.SearchBar">
<item name="android:background">@color/white</item>
<item name="android:textColor">@color/black</item>
</style>
<!-- etcetera... -->
So, I replaced the hardcoded atributes by one of these styles in the XML objects within activities and fragments. This works fine. (please notice that different XML "view objects" might use one or another of all these styles).
And here comes the question:
So, let's imagine that I take all those styles and make a copy of every single one of them, but with different name: instead of naming them My_DarkMode
or My_DarkMode.*
, I name them My_LightMode
, and change completely the color palette for these "LightMode styles" (so, using them like some kind of theme whatsoever).
So, the idea would be switching programatically this:
<!-- It's a little pseudo-code, for summarizing the thing -->
<TextView
style="@style/My_DarkMode.TextView"
android:id="[...]" />
<TextView
style="@style/My_DarkMode.HighligthedText"
android:id="[...]" />
<!-- [...] -->
...into this (but for much more XML elements than this):
<TextView
style="@style/My_LightMode.TextView"
android:id="[...]" />
<TextView
style="@style/My_LightMode.HighlightedText"
android:id="[...]" />
<!-- [...] -->
What would be the proper way to, by Java (y'know, by clicking some button or something like that: I'm not concerned about how to trigger it for this question, but rather which instructions should I use), switching the styles to be applied? Can't I somehow group all those styles into a single theme or something? It looks like I have no choice but to do something similar to this, because if I apply some of this from the theme and let inheritance do its stuff, then the SearchView inherits white letters (with white background; so you can see what I mean by chaos)... but also, my knowledge about Android styles and themes is, indeed, limited.
For the record
I am aware that this approach of mine might not be a good one at all. Among other things: because of my ignorance about how Styles, Themes and style inheritance hierarchy works in Android. (I mean, maybe my XML code would be too WET if I keep this approach? I wonder...) If so, a more clean approach is welcome.
If this was HTML and CSS instead, I would be able to figure this out much more easier for some reason, or so I think...
EDIT: For real: no matter how much I read docs like Themes or how the theme main color attribute work... the more I read, the more confused I get. Trial and error is not helping much either... recently I tried to remove all styles from XML layouts and start the theme from scratch; and trying what it is inside this link i find out that if I do this:
<item name="colorBackground">@color/purple_500</item>
...colorBackground
just doesn't exist! One more of countless times that something didn't work as in the docs... sigh...
So here goes: the "theme from scratch". Forget all style=
that I set up earlier: I removed them all.
My themes.xml
:
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- all these ones were before, I started tweaking
them and see what happens -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/white</item>
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- <item name="toolbarStyle">@style/My_DarkMode.MaterialToolbar</item> -->
<item name="toolbarStyle">@style/Widget.MaterialComponents.Toolbar.PrimarySurface</item>
<item name="drawerArrowStyle">@style/Theme.MyApp.DrawerArrowStyle</item>
<!-- and here I add new ones I din't knew before
and start playing with them like crazy -->
<item name="colorSurface">@color/activity_grey</item>
<item name="colorOnSurface">@color/white</item>
<item name="colorOnPrimarySurface">@color/yellow_4text</item>
<item name="colorContainer">@color/activity_grey</item>
<item name="colorOnBackground">@color/yellow_4text</item>
<!-- It doesn't exist... sigh... vVv -->
<!-- <item name="colorBackground">@color/black</item> -->
</style>
I am having a really hard time trying to imagine, discover or reach which general theme attributes to tweak for trivialities like having all TextViews showing text with the same color, or why colorSurface
or colorContainer
paint grey the <NavigationView>
, but not the <ConstraintLayout>
's backgrounds?? I am trying to keep everything as similar as it was before, but with a centralized theme that I can switch from a single place programatically.
I read lots of links in "Android Developers" about styles and themes and how they are supposed to work together... but they don't clearly show howto! It would be great if there was a canonical way to join several styles in a single theme or something like that... so, you could apply different styles to different views by just switching the theme, just like it would work, more or less, with CSS classes.
Old:
(before wanting to extract a theme)
New mess:
(removed styles from Layouts and started modifying Theme from scratch)