I'm using Android Studio Electric Eel and I started with a new "Basic Activity" project. It comes with a light and dark theme, /res/values/theme.xml /res/values-night/theme.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Example" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimary">@color/md_theme_light_primary</item>
</style>
</resources>
I understand I need to use this code:
val typedValue = TypedValue()
view.context.theme.resolveAttribute(R.attr.colorPrimary, typedValue, true)
val colorPrimary = typedValue.data
And that works almost.
For whatever reason, R.attr.colorPrimary
won't resolve off of the default com.example.project.R
that is my local project. When I type R.attr.colorPrimary
it only auto-complete resolves to com.google.android.material.R.attr.colorPrimary
(it also can resolve to some androidx components, that also work)
When I use that, it does work, and it does use my colors.xml pointed to from my theme.xml. I just want to understand why it won't simply resolve from my theme.xml. In all the examples I found online it was named styles.xml so I renamed it to that, and everything worked identically, no change.
When I ctrl-click the resolved color it takes me to a cached file in ...\transformed\appcompat-1.6.1\res\values\values.xml that's <attr format="color" name="colorPrimary"/>
And if I ctrl-click the parent="Theme.MaterialComponents.DayNight.DarkActionBar"
it takes me to a cache of ...\transformed\material-1.8.0\res\values\values.xml
I just want to understand why. It seems my colors still override the default ones and it works using the com.google.android.material.R
. In xml layouts ?attr/colorPrimary
works just fine. But in nowhere that I looked did it say that when programmatically resolving it needed that path.
And that works almost. For whatever reason, R.attr.colorPrimary won't resolve off of the default com.example.project.R that is my local project.
That's because colorPrimary
is not an attribute that you've defined in your local project. It's an attribute that is defined in the material library.
When I use that, it does work, and it does use my colors.xml pointed to from my theme.xml. I just want to understand why it won't simply resolve from my theme.xml.
An attribute doesn't "resolve from [your] theme.xml". An attribute is defined in an attrs.xml
file just like colors or dimens. You've not defined one, hence it does not exist.
When you use it in your themes.xml
file as so:
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.Example" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimary">@color/md_theme_light_primary</item>
</style>
</resources>
You are extending the existing material theme (the parent
attribute) and setting the colorPrimary
attribute that is already defined in that theme. You are not declaring your own colorPrimary
attribute. If you did not set the parent
attribute to a theme that had colorPrimary
, you would get an error.
In all the examples I found online it was named styles.xml so I renamed it to that, and everything worked identically, no change.
Right - the name of the file is irrelevant.
When I ctrl-click the resolved color it takes me to a cached file in ...\transformed\appcompat-1.6.1\res\values\values.xml that's
And if I ctrl-click the parent="Theme.MaterialComponents.DayNight.DarkActionBar" it takes me to a cache of ...\transformed\material-1.8.0\res\values\values.xml
Android theming via XML is a complicated web of nested overrides. colorPrimary
as a concept was introduced with Material design in the first "app compat" libraries. It's since been updated and enhanced with dedicated material libraries that extend the original and redefine the values to adhere to the latest Material Guidelines.
I just want to understand why. It seems my colors still override the default ones and it works using the com.google.android.material.R. In xml layouts ?attr/colorPrimary works just fine. But in nowhere that I looked did it say that when programmatically resolving it needed that path.
In summary, colorPrimary
is a theme attribute defined by the appcompat and material design libraries, so it lives within their package.
In XML, ?attr/colorPrimary
references the current theme which in your case will be "Theme.Example", which you've declared to set colorPrimary
to @color/md_theme_light_primary
.
In code, though, colorPrimary
is just a constant and must be resolved to clarify which colorPrimary
of all those that have been defined you're referring to. Ultimately, it doesn't really matter which package you use to access colorPrimary
in code - its value will resolve to what you have set in your theme.