91

I am looking at the Honeycomb Gallery sample code (here) and I ran across the following code while trying to add action items in my own app:

<item android:id="@+id/camera"
    android:title="Camera"
    android:icon="?attr/menuIconCamera"
    android:showAsAction="ifRoom" />

The ?attr is throwing me for a loop. Can someone please explain what this is doing? How is this related to a drawable? I can't seem to find any good information on Google. Also is there a listing or gallery of attributes we can use for icons instead of just menuIconCamera?

Thanks

Edit: I did some more looking around and found that attrs.xml looks like this:

<resources>
<declare-styleable name="AppTheme">
    <attr name="listDragShadowBackground" format="reference" />
    <attr name="menuIconCamera" format="reference" />
    <attr name="menuIconToggle" format="reference" />
    <attr name="menuIconShare" format="reference" />
</declare-styleable>

Unfortunately that just makes it even more confusing for me. What is this doing?

FuegoFingers
  • 2,181
  • 6
  • 27
  • 36

6 Answers6

65

The ?attr/menuIconCamera value means that an icon from menuIconCamera attribute of the current theme will be used.

There must be a drawable assigned to the menuIconCamera attribute somewhere in the themes.xml file. If there're two themes with different values of this attribute then actual icon will depend on a theme which is currently used.

The attrs.xml file is used to define custom attributes. Without this definition compiler will treat unknown attributes as erroneous.

Michael
  • 53,859
  • 22
  • 133
  • 139
  • 1
    you are exactly right, @drawable/ic_menu_camera_holo_light, Thank you so much. I see that ic_menu_camera_holo_light is a local drawable. Does 3.x not have public icons built in like 2.x had? – FuegoFingers Sep 21 '11 at 19:02
  • I don't think it's somehow connected to Android version. This is just a way of making attributes dependent on a chosen theme. – Michael Sep 21 '11 at 19:30
52

The ?attr: syntax is used for accessing attributes of current theme. See referencing style attributes.

Melquiades
  • 8,496
  • 1
  • 31
  • 46
Peter Knego
  • 79,991
  • 11
  • 123
  • 154
  • 3
    The supplied link was very, very helpful. Thanks! – sven Oct 28 '11 at 11:19
  • 3
    Very helpful, but you should still post the main parts of that link. – gustavohenke Sep 16 '15 at 04:49
  • 1
    This was the most helpful part of the linked article: 'A style attribute resource allows you to reference the value of an attribute in the currently-applied theme. Referencing a style attribute allows you to customize the look of UI elements by styling them to match standard variations supplied by the current theme, instead of supplying a hard-coded value. Referencing a style attribute essentially says, "use the style that is defined by this attribute, in the current theme."' – bigtex777 Aug 25 '16 at 03:41
25

I know this post is very old, but I feel the following explanation will help beginners understand it easily.

So in layman's terms,

someAttribute="?attr/attributeName" means -

set the value of someAttribute to whatever is the value of attributeName in current theme

A common example occurs in styling a Toolbar

<style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/primary_color</item>
       //some more stuff here
</style>
<!-- custom toolbar style -->
<style name="myToolbar" parent="Widget.AppCompat.Toolbar">
      <item name="android:background">?attr/colorPrimary</item>
     //some code here
</style>

Here value of android:background will be set to @color/primary_color because ?attr/colorPrimary refers to @color/primary_color in the current theme (AppTheme)

sziraqui
  • 5,763
  • 3
  • 28
  • 37
17

My English is not good, sorry. But I know this question

android:icon="?attr/menuIconCamera" want use

attrs.xml

<resources>
    <declare-styleable name="AppTheme">
        <attr name="listDragShadowBackground" format="reference" />
        <attr name="menuIconCamera" format="reference" />
        <attr name="menuIconToggle" format="reference" />
        <attr name="menuIconShare" format="reference" />
    </declare-styleable>
</resources>

styles.xml

<style name="AppTheme.Light" parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarStyle">@style/ActionBar.Light</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="listDragShadowBackground">@android:color/background_light</item>
        <item name="menuIconCamera">@drawable/ic_menu_camera_holo_light</item> //this....
        <item name="menuIconToggle">@drawable/ic_menu_toggle_holo_light</item>
        <item name="menuIconShare">@drawable/ic_menu_share_holo_light</item>
    </style>

use @drawable/ic_menu_camera_holo_light

The_Fox
  • 6,992
  • 2
  • 43
  • 69
dawn
  • 171
  • 1
  • 2
4

This blog post does an amazing job going over how to reference values for style-attributes that are defined in the current theme: https://trickyandroid.com/android-resources-and-style-attributes-cheatsheet/

  • When you see ? notation - it means that we are trying to reference a style attribute - a value which may vary depending on current theme. In each specific theme we can override this attribute, so the XML layout doesn't need to be changed, and the correct theme needs to be applied.

  • When you see the @ notation - we reference actual resource value (color, string, dimension, etc). This resource should have an actual value. In this case we know exactly what value we are dealing with.

Here's an example:

    <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="LauncherButton" parent="TextAppearance.AppCompat.Medium">
        <item name="android:textColor">?colorAccent</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_centerHorizontal">true</item>
        <item name="android:textAllCaps">false</item>
    </style>
nazmul idris
  • 432
  • 6
  • 17
4

This is for refering style Attributes. see R.attr

?[<package_name>:][<resource_type>/]<resource_name>

Referencing style attributes

Michele
  • 6,126
  • 2
  • 41
  • 45
  • 3
    One thing that doesn't seem to be documented anywhere is that '' is the full package name of whatever declared the resource. More specically, it's not an XML namespace prefix, even though the syntax might suggest that. For example to refer to an attr declared by the appcompat library, use `android.support.v7.appcompat:`. – Stop Harming the Community Jun 05 '14 at 16:04