Skip to main content

04 - Android Resources

All in some /res subdirectory

  • ./anim – Animations
  • ./color – Colors and Color State lists
  • ./drawable – Picures (binary and xml)
  • ./layout – Layouts
  • ./menu – Menus
  • ./mipmap – launcher icons only
  • ./raw – Misc files (audio, video, etc)
  • ./values – texts, sizes, styles
  • ./xml – xml files
  • ...

Animation

  • Property animation
    • Modify objects property values over a time with an Animator
  • View animation
    • Tween animation – series on transformations on single image with Animation
    • Frame animation – sequence of images with AnimationDrawable

Color

  • File location res/color/filename.xml
  • Resource reference R.color.filename
  • Android:color
    • The value always begins with a hash (#) character and then followed by the Alpha-Red-Green-Blue information in one of the following formats:
    • #RGB
    • #ARGB
    • #RRGGBB
    • #AARRGGBB
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:color="hex_color"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>

res/color/button_text.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#ffff0000"
android:state_pressed="true" /> <!-- pressed -->
<item android:color="#ff0000ff"
android:state_focused="true" /> <!-- focused -->
<item android:color="#ff000000" /> <!-- default -->
</selector>
<Button 
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button_text"
android:textColor="@color/button_text" />

Drawable

  • Graphics that can be drawn
    • Retrieve with APIs such as getDrawable(…)
    • Apply to other XML using android:drawable and android:icon
  • BitmapDrawable – .png, .jpg, .gif
  • NinePatchDrawable - .9.png – PNG with stretchable regions
  • Layer List – array of other Drawables. Drawn in order, largest index on top
  • State List – differen bitmap graphics for different states (dif image when button is pressed)
  • Transition Drawable – can crossfade between two drawables
  • Inset, Clip, Scale, Shape….

Bitmap

  • .png preferred, .jpg acceptable, .gif discouraged
  • File location
    /res/drawable/filename.png
  • XML bitmap
    /res/drawable/filename.xml
  • Nine-patch
    • PNG image in which you can define stretchable regions
    • Usually background of a View that has at least one dimension set to "wrap_content"

Configuration qualifiers

To ensure your resources look their best, you should include alternative versions for different screen possibilities.

  • ldpi (low)
  • mdpi (medium)
  • hdpi (high)
  • xhdpi extra-high)
  • xxhdpi (extra-extra-high)
  • xxxhdpi (extra-extra-extra-high)
  • nodpi (no scaling)
  • port (portrait)
  • land (landscape)
  • long (long aspect ratio)
  • notlong (normal aspect ratio)
  • small, normal, large, xlarge (screen size)

Folder name example:
res/layout-xlarge-land/my_layout.xml

Screen size and density

Size

  • xlarge screens are at least 960dp x 720dp
  • large screens are at least 640dp x 480dp
  • normal screens are at least 470dp x 320dp
  • small screens are at least 426dp x 320dp

Density

  • ldpi (low) ~120dpi
  • mdpi (medium) ~160dpi
  • hdpi (high) ~240dpi
  • xhdpi (extra-high) ~320dpi
  • xxhdpi (extra-extra-high) ~480dpi
  • xxxhdpi (extra-extra-extra-high) ~640dpi

layout

Layer list

  • Array of other drawables
  • Last drawable in top
  • /res/drawable/filename.xml

layout

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:gravity="center"
android:src="@drawable/android_red" />
</item>
<item android:left="10dp" android:top="10dp">
<bitmap
android:gravity="center"
android:src="@drawable/android_green" />
</item>
<item android:left="20dp" android:top="20dp">
<bitmap
android:gravity="center"
android:src="@drawable/android_blue" />
</item>
</layer-list>
<ImageView  
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/layers" />

State list

Different images to represent the same graphic, depending on the state of the object
/res/drawable/filename.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize=["true" | "false"]
android:dither=["true" | "false"]
android:variablePadding=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_hovered=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_activated=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_pressed"
android:state_pressed="true" /> <!-- pressed -->
<item android:drawable="@drawable/button_focused"
android:state_focused="true" /> <!-- focused -->
<item android:drawable="@drawable/button_focused"
android:state_hovered="true" /> <!-- hovered -->
<item android:drawable="@drawable/button_normal" /> <!-- default -->
</selector>
<Button  
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/button" />

Transition

Can cross-fade between the two drawable resources.

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:bottom="dimension"
android:drawable="@[package:]drawable/drawable_resource"
android:id="@[+][package:]id/resource_name"
android:left="dimension"
android:right="dimension"
android:top="dimension" />
</transition>
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/on" />
<item android:drawable="@drawable/off" />
</transition>
<ImageButton 
android:id="@+id/button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/transition" />
ImageButton button = (ImageButton) findViewById(R.id.button);
TransitionDrawable drawable = (TransitionDrawable)
button.getDrawable();
drawable.startTransition(500);

Options Menu, Context Menu, or submenu

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@[+][package:]id/resource_name"
android:title="string"
android:titleCondensed="string"
android:icon="@[package:]drawable/drawable_resource_name"
android:onClick="method name"
android:showAsAction=["ifRoom" | "never" | "withText" | "always" | "collapseActionView"]
android:actionLayout="@[package:]layout/layout_resource_name"
android:actionViewClass="class name"
android:actionProviderClass="class name"
android:alphabeticShortcut="string"
android:numericShortcut="string"
android:checkable=["true" | "false"]
android:visible=["true" | "false"]
android:enabled=["true" | "false"]
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="integer" />
<group android:id="@[+][package:]id/resource name"
android:checkableBehavior=["none" | "all" | "single"]
android:visible=["true" | "false"]
android:enabled=["true" | "false"]
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="integer" >
<item />
</group>
<item >
<menu>
<item />
</menu>
</item>
</menu>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/item1"
android:title="@string/item1"
android:icon="@drawable/group_item1_icon"
android:showAsAction="ifRoom|withText"/>
<group android:id="@+id/group">
<item android:id="@+id/group_item1"
android:onClick="onGroupItemClick"
android:title="@string/group_item1"
android:icon="@drawable/group_item1_icon" />
<item android:id="@+id/group_item2"
android:onClick="onGroupItemClick"
android:title="@string/group_item2"
android:icon="@drawable/group_item2_icon" />
</group>
<item android:id="@+id/submenu"
android:title="@string/submenu_title"
android:showAsAction="ifRoom|withText" >
<menu>
<item android:id="@+id/submenu_item1"
android:title="@string/submenu_item1" />
</menu>
</item>
</menu>
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.example_menu, menu);
    return true;
}

public void onGroupItemClick(MenuItem item) {
    // One of the group items (using the onClick attribute) was clicked
    // The item parameter passed here indicates which item it is
    // All other menu item clicks are handled by onOptionsItemSelected()
}

Values

Typed array

res/values/filename.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array
        name="array_name">
        <item>resource</item>
    </array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="icons">
        <item>@drawable/home</item>
        <item>@drawable/settings</item>
        <item>@drawable/logout</item>
    <array>
</resources>
Resources res = getResources();
TypedArray icons = res.obtainTypedArray(R.array.icons);
Drawable drawable = icons.getDrawable(0);

Colors

  • res/values/colors.xml
  • R.color.color_name
  • The value always begins with a pound (#) character and then followed by the Alpha-Red-Green-Blue information in one of the following formats:
    • #RGB
    • #ARGB
    • #RRGGBB
    • #AARRGGBB
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="color_name">hex_color</color>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="opaque_red">#f00</color>
   <color name="translucent_red">#80ff0000</color>
</resources>
Resources res = getResources();
int color = res.getColor(R.color.opaque_red);
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/translucent_red"
    android:text="Hello"/>

Dimensions

  • res/values/filename.xml
  • R.dimen.dimension_name
    • dp - Density-independent Pixels
    • sp - Scale-independent Pixels ( scaled by the user's font size preference)
    • pt - Points - 1/72 of an inch based on the physical size of the screen.
    • px - Pixels - Corresponds to actual pixels on the screen.
    • mm - Millimeters - Based on the physical size of the screen
    • in - Inches - Based on the physical size of the screen.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="dimension_name">dimension</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="textview_height">25dp</dimen>
    <dimen name="textview_width">150dp</dimen>
    <dimen name="ball_radius">30dp</dimen>
    <dimen name="font_size">16sp</dimen>
</resources>
Resources res = getResources();
float fontSize = res.getDimension(R.dimen.font_size);
<TextView
    android:layout_height="@dimen/textview_height"
    android:layout_width="@dimen/textview_width"
    android:textSize="@dimen/font_size"/>

Strings

  • res/values/filename.xml
  • R.string.string_name
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="string_name">text_string</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" />
String string = getString(R.string.hello); 

String array

  • res/values/filename.xml
  • R.array.string_array_name
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="string_array_name">
        <item>text_string</item>
    </string-array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="planets_array">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
        <item>Mars</item>
    </string-array>
</resources>
Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);

Quantity strings (plurals)

  • res/values/filename.xml
  • R.plurals.plural_name
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals
        name="plural_name">
        <item
            quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
            >text_string</item>
    </plurals>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="numberOfSongsAvailable">
        <!--
             As a developer, you should always supply "one" and "other"
             strings. Your translators will know which strings are actually
             needed for their language. Always include %d in "one" because
             translators will need to use %d for languages where "one"
             doesn't mean 1 (as explained above).
          -->
        <item quantity="one">%d song found.</item>
        <item quantity="other">%d songs found.</item>
    </plurals>
</resources>
int count = getNumberOfsongsAvailable();
Resources res = getResources();
String songsFound = res.getQuantityString(R.plurals.numberOfSongsAvailable, count, count);

layout

Style

  • Style resource defines the format and look for a UI.
  • res/values/filename.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style
        name="style_name"
        parent="@[package:]style/style_to_inherit">
        <item
            name="[package:]style_property_name"
            >style_value</item>
    </style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CustomText" parent="@style/Text">
        <item name="android:textSize">20sp</item>
        <item name="android:textColor">#008</item>
    </style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<EditText
    style="@style/CustomText"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Hello, World!" />