Few days ago I stumbled upon one of my early-Android-dev-days cheatsheet I created for understanding different syntax when dealing with Android resources and theme attributes.
Surprisingly, I found it quite useful now, so I decided to make it more blogpost-ready and share with others.
Just so you understand what I will be talking about today, consider following ways to set view's background color via xml layout:
android:background="@color/colorPrimary" android:background="@com.myapp:color/colorPrimary" android:background="?colorPrimary" android:background="?attr/colorPrimary" android:background="?com.myapp:attr/colorPrimary" android:background="?com.myapp:colorPrimary" android:background="?android:colorPrimary" android:background="?android:attr/colorPrimary"
Exciting, isn't it? Well, I hope I'll try to break it down, so it doesn't look this scary anymore.
Referencing resources vs style attributes
This is a small detour into Android basics since it is really important to understand the difference between
? before we move any further.
When we use
@ - we reference actual resource value (color, string, dimension, etc). I.e. this resource should have an actual value. In this case we know exactly what value we are dealing with.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> </resources>
So when we try to reference this value in xml (
android:background="@color/colorPrimary"), background will be set to color
#3F51B5 no matter what theme is currently set for this activity.
On the other side, when you see
? notation - it means that we are trying to reference a style attribute - a value which may vary depending on current theme. I.e. in each specific theme I can override this attribute, so I don't need to change my XML layout - I just need to apply proper theme:
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light"> <item name="colorPrimary">#F00</item> </style> </resources>
<TextView android:id="@+id/my_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="?colorPrimary"/>
In this case, we ask Android: "Hey, give me a value of
colorPrimary attribute which is specified in current theme". In this case it is a bit harder to tell exactly what color our background is going to be since it really depends on theme applied to the activity this layout belongs to.
Now let's see what is the actual syntax for referencing different resources.
Referencing resources (
package_name- optional name of the package this resource belongs to (by default - your app package). Reserved package -
android. Used for resources shipping with platform
resource_type- the R subclass for the resource type (
resource_name- an actual name of the resource we are trying to reference.
Let's actually take my first 2 examples and try to break them down:
As you can see - both of them are equivalent since by default, package name is set to our app's package name, so it is not necessary to mention it:
- package(optional) =
- resource_type =
- resource_name =
As you might think, Android ships with some predefined resources for entire OS. F.i. I could reference some built-in color this way:
Here is what we got in this case:
- package =
android- referencing built-in resources
- resource_type =
- resource_name =
Nowadays, lots of people use AppCompat (and if you don't - you probably should), and AppCompat often defines its own resources. Even though AppCompat is a first-party lib shipped by Google, it is not really a part of operating system. Instead, those resources get merged into your app, so you don't need to use
android keyword to reference those.
Here, even though we don't have custom style attribute name
selectableItemBackground in our app (notice that we didn't use
android: prefix), we can still reference it because it was "added" to our app by AppCompat.
Referencing style attributes (
Guess what. The syntax is pretty similar to resources:
There one small difference though.
The only allowed
resource_type when referencing style attributes is
attr. So given that, Android packaging tool actually allows us to omit
resource_type, so it is effectively optional.
So following expressions mean exactly the same thing from Android perspective:
android:background="?com.myapp:attr/colorPrimary" //verbose format android:background="?com.myapp:colorPrimary" //attr is skipped since its optional android:background="?attr/colorPrimary" //package is skipped since its optional android:background="?colorPrimary" // package & attr is skipped
As you can see, syntax is super simple after all. Never get confused again!