I have defined colors in colors.xml like below
<resources>
<color name="primary">#5D4037</color>
<color name="primary_dark">#4E342E</color>
<color name="accent">#FF3D00</color>
</resources>
I have also defined themes in styles.xml, like below
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
</style>
Also, at many places in code, I have used these colors to set it for text, etc.
Now I want to give option to users to change the colors. I read that I can't change colors specified in colors.xml. Also, even if I change the theme, the color referenced can't be changed. So specifying more themes (with hard-coded colors) could be an option, but in that case what will happen to elements which has got color dynamically? Also, user cannot select any color but has to use only the colors specified by me in themes.
Am I missing something obvious? How this can be done?
You cannot change values in your resource files at runtime.
If you want to allow your users to customize the colors in your app, you will need to store an manage those colors yourself, perhaps using resource files to provide defaults or to store the options that users can select from.
Related
I have been learning MDC from google code lab, and it is a well designed application to know how material design works. However, in a particular section they showed how to use dark theme. The did it by changing the theme attributes from style.xml. Being resourceful, I have been trying to learn how to use multiple theme and interchange them runtime.
For this reason I avoided their hard-coded way and tried to inherit the base theme and put changes according to my need. Below I am putting some changes in the theme file
<!--Dark Theme style !-->
<style name="Theme.Shrine.Dark" parent="Theme.Shrine">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/darkColorPrimaryDark</item>
<item name="colorPrimaryDark">#color/darkColorPrimaryDark</item>
<item name="colorAccent">#color/darkColorAccent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<item name="android:textColorPrimary">#color/darkTextColorPrimary</item>
<item name="colorControlActivated">#color/darkColorControlActivated</item>
<item name="toolBarStyle">#style/Widget.Shrine.Toolbar.Dark</item>
<item name="appBackGroundColor">#color/darkBackgroundColor</item>
</style>
There are some changes but they are irreverent to my problem, so I am not going to add them here. Anyway, with changes in my style file app looks something like this
Everything is expected except for icon colour in toolbar. So I check into the code and find every icon colour is referenced from the their respective from drawable file with android:tint="#color/toolbarIconColor" and in color.xml toolbarcolor is <color name="toolbarIconColor">#color/textColorPrimary</color>
It shows wrong color in dark mode, in this case how can I show yellow color in dark mode. I have changed textColoeSecondary from base theme of dark theme but it didn't work
Firstly, you need to remove hard reference of colour from every drawables which reflect different colours depending on app theme. So, add attrs.xml in your values directory. and add the reference name for icon colour such as this one
<attr name="toolbarIconColor" format="reference"/>
Secondly, add two different colour for two themes. For example, for normal theme <color name="toolbarIconColor">#color/textColorPrimary</color> and for dark one use <color name="darkToolbarIconColor">#FFCF44</color>
Finally, go to your style.xml file and make this change to hook up with the reference we have added in attrs.xml file, like this one for normal theme <item name="toolbarIconColor">#color/toolbarIconColor</item> and <item name="toolbarIconColor">#color/darkToolbarIconColor</item>
I get this as one of my colors generated by the Material Design Color Platte.
But in this image:
I don't see colorPrimaryLight anywhere. What is it used for and how do I declare it? Do declare it like this in my style?:
<item name="colorPrimaryLight">#color/colorPrimaryLight</item>
Or do I declare it in a different way? And what is it used for?
By default, the statusBarColor is set to colorPrimaryDark. If you want to use colorPrimaryLight for the status bar you need to set android:statusBarColor to android:colorPrimaryLight.
https://developer.android.com/training/material/theme.html
in your resources file put:
<color name="colorPrimaryLight">#D1C4E9</color>
in your styles file put:
<item name="colorPrimaryLight">#color/colorPrimaryLight</item>
TL;DR: colorPrimaryLight is one of several colors identified as part of the Material palette that is not actually mapped to a Theme attribute in Android. The guidelines recommend using it in several areas such as a TabLayout backgrounds.
I cannot find an authoritative source about using this attribute in Android apps, but it seems that Material defines a large number of colors, as shown on this helpful page, but not all of them are mapped to Android Theme attributes. For instance, if you create a brand new single-Activity project in Android Studio and modify styles.xml as shown below:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<!-- THIS THEME ATTRIBUTE IS NOT FOUND -->
<item name="colorPrimaryLight">#color/colorPrimary</item>
</style>
</resources>
The colorPrimaryLight attribute is not found by the compiler.
Therefore if you wanted to use it in your application you would presumably have to explicitly link to a color.xml resource. This seems to negate the benefit of the Theme system somewhat, but perhaps I am missing a trick.
I am trying to change the color of my Hello World app.
Right now it looks like this in the emulator (purple bar, pink floating icon):
But when I change the theme setting, I get a bunch of rendering errors (note that I tried to choose Material Light):
And when I try to run the app again it still looks purple/pink as it did in the first pic. I'm not really sure how to make heads or tails of these kinds of errors or how I am supposed to fix them.
You are changing the theme of the preview window. This is used to view how your layout would look using a given theme. It does not change the theming on your phone when running your app—it is just a preview.
To actually change the colors you need to change the theme. Usually this would be the AppTheme that is referencing some colors.
Locate your colors.xml in res/values/ and modify the colors there:
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>
These colors get used by the theme generated at project creation, looking like this in styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
You could also remove the reference and edit the colors in the theme directly, but that is usually not the clean way. Your styles.xml would also be the right place to add more themes—which in turn you could preview in Android Studio.
Starting to get my hands into that new update to the Google Support Library and I want to implement the Theme.AppCompat.DayNight into my app.
The problem I am having is that it seems no one explained how to customize it. So If I want to have a different colorAccent for day and a different one for night, how do I do that? Are you supposed to specify different dark and light themes to base off of? Thanks in advance!
You can use the night resource qualifier folder.
In this way you can define colors and the other resources for the dark (night) and for the light theme (day).
Qualifiers:
night: Night time
notnight: Day time
In order to support the dark theme with a Material Components Theme use:
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight">
<!-- ... -->
</style>
With an AppCompat theme:
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
<item name="colorPrimary">#color/primary</item>
</style>
Then define in your app theme the references color resources, and override the value in the values-night directory if needed:
Example: res\values\colors.xml:
<color name="colorPrimary">.....</color>
In res\values-night\colors.xml folders define the same color:
<color name="colorPrimary">.....</color>
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.