I have an app with a few different Activities
. The different activities have different styled buttons, texts, etc... I've set up all the components to have various styles based on their location/Activity. (Eg. style="@style/MainMenuActionBarTitle
, or style="@style/MainMenuActionBarTagLine
). These styles set the background
(Drawable
, MipMap
, or Color
), textColor
, etc...
The app will be offering some theme packs which change the colors of these various components throughout the application, and I was hoping there was a way to have Styles
with the same name, but different values based on the Theme
of the app. This way I can just change the Theme
whenever the Activity
is loaded to whatever Theme the user has chosen.
There's some good info here on how to change the standard widget look & feel using Themes, but that changes the look and feel for the standard-un-styled widgets.
Is there a way to accomplish this using Themes, or is this the wrong direction altogether? Is there a better/easier route?
Edit: After doing more research and more fiddling, I've realized what I want to do isn't far off from how I can accomplish this. What I want to do is to actually change component Styles
when I set the Theme
of the Activity
.
One solution I've discovered is to use attributes
which the Theme
can point to different Styles
.
attrs.xml
<resources>
<!-- Attributes referencing whatever style the theme needs to set up. -->
<attr name="main_menu_button_style_play" format="reference" />
</resources>
themes.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- App specific attributes -->
<item name="@attr/main_menu_button_style_play">@style/MainMenu.Button.Play</item>
</style>
<!-- Blue application theme. -->
<style name="AppTheme.Blue" parent="AppTheme">
<!-- App specific attributes -->
<item name="@attr/main_menu_button_style_play">@style/MainMenu.Button.Play.Blue</item>
</style>
</resources>
styles.xml
<style name="MainMenu.Button.Play">
<item name="android:background">#f76d3c</item>
<item name="android:text">PLAY</item>
</style>
<style name="MainMenu.Button.Play.Blue">
<item name="android:background">#2ca8c2</item>
</style>
activity.xml
<Button android:id="@+id/main_play_button"
style="?attr/main_menu_button_style_play"/>
This works really well, and allows me to set the Theme
in the Activity.onCreate()
method.
The only annoying problem I have with this solution is that Android Studio complains that the Button
is missing the layout_width
and layout_height
even though they're defined in the Style
. I guess it doesn't follow the attribute reference back through the chosen Theme
.
Another approach which is what I ended up using was to more heavily use the attributes. Creating attributes for all the properties values I want to change between themes. So, instead of main_menu_button_style_play
which defines the style reference, I used main_menu_button_play_background
. This approach is the same amount of work as simply specifying a style because themes can inherit, but the IDE understands it.