Support free tutorials









vogella training Training Books



Android Drawables - Tutorial

Lars Vogel

Version 2.1

01.09.2010 - 20.12.2012

Revision History
Revision 0.1 01.09.2010 Lars
Vogel
Created
Revision 0.2 - 2.1 13.12.2010 - 20.12.2012 Lars
Vogel
bug fixes and enhancements

Android Drawables

This tutorial describes the usage of Drawables in Android.


Table of Contents

1. What are Drawables?
2. Using drawables for views
3. Loading Bitmaps and Drawables
4. XML Drawables
4.1. Shape Drawables
4.2. State Drawables
4.3. Transition Drawables
5. Vector drawables
6. Animation Drawables
7. 9 Patch Drawables
8. Custom Drawables
9. Exercise: Create Custom Drawables
10. Support this website
10.1. Thank you
10.2. Questions and Discussion
11. Links and Literature
11.1. Source Code
11.2. Android Widget Resources
11.3. Android Resources
11.4. vogella Resources

1. What are Drawables?

A Drawable resource is a general concept for a graphic which can be drawn. The simplest case is a graphical file (bitmap), which would be represented in Android via a BitmapDrawable class.

Every Drawable is stored as individual files in one of the res/drawable folders. Typically you would store bitmaps for different resolutions in the -mdpi, -hdpi, -xhdpi, -xxhdpi subfolders of res/drawable. The ADT project creation wizard creates these folders by default. If these bitmaps are provided in different folder, the Android system selects the correct one automatically based on the device configuration.

If you do not provide bitmaps for all supported resolutions, the the Android system scales the closest fit up or down. This is typically undesired as the bitmap might get blury.

In addition to graphical files, Android supports XML drawables and 9-patch graphics. XML drawables are used to describe shapes (color, border, gradient), state, transitions and more.

9-patch graphics are used to define which part of a graphic should be stretched if the view which uses this graphic is larger than the graphic.

Drawables can also be written in Java code. Every object which implements Drawable can be used as a Drawable in code.

2. Using drawables for views

Drawables are referred to in XML via @drawable/filename whereby filename filename is the filename without the file extension. For example to access the res/drawable/hello.png Drawable, you would use @drawable/hello as demonstrated in the following snippet.

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/hello"
    android:text="@string/hello_world" /> 

In code you can also assign drawables to views. Most views accept an resource ID as input parameter. For example the following code shows how to set a drawables as background to an ImageView.

ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageResource(R.drawable.hello); 

3. Loading Bitmaps and Drawables

Android allows you to use the Bitmap class for working with bitmaps. This section explain how to create Bitmap objects via Java code and how to convert Bitmap into Drawable objects and vice versa.

If required you can load any accessible bitmap file in your code and convert them into Drawables objects.

The following example code shows how to create an Bitmap object for the assets folder and assign it to an ImageView.

// Get the AssetManager
    AssetManager manager = getAssets();

    // read a Bitmap from Assets
    InputStream open = null;
    try {
      open = manager.open("logo.png");
      Bitmap bitmap = BitmapFactory.decodeStream(open);
      // Assign the bitmap to an ImageView in this layout
      ImageView view = (ImageView) findViewById(R.id.imageView1);
      view.setImageBitmap(bitmap);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (open != null) {
        try {
          open.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    } 

You can also access the Drawables from your res/drawable folder as Bitmap objects in your source code. The following code demonstrates that.

Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_search); 

You can create a scale bitmap based on a new weight and height definition in pixel.

Bitmap originalBitmap = <initial setup>;

Bitmap resizedBitmap = 
   Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, false); 

To convert a Bitmap object into a Drawable you can use the following code.

# Convert Bitmap to Drawable
Drawable d = new BitmapDrawable(getResources(),bitmap); 

4. XML Drawables

4.1. Shape Drawables

Shape Drawables are XML files which allow to define a geometric object with colors, borders and gradients which can get assigned to Views. The advantage of using XML Shape Drawables is that they automatically adjust to the correct size.

The following listing shows an example of a Shape Drawable.

<?xml version="1.0" encoding="UTF-8"?>
<shape
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <stroke
    android:width="2dp"
    android:color="#FFFFFFFF" />
  <gradient
    android:endColor="#DDBBBBBB"
    android:startColor="#DD777777"
    android:angle="90" />
  <corners
    android:bottomRightRadius="7dp"
    android:bottomLeftRadius="7dp"
    android:topLeftRadius="7dp"
    android:topRightRadius="7dp" />
</shape> 

You could for example assign that drawable to the background property of your layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/myshape"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
   >
    </EditText>

    <RadioGroup
        android:id="@+id/radioGroup1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <RadioButton
            android:id="@+id/radio0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="@string/celsius" >
        </RadioButton>

        <RadioButton
            android:id="@+id/radio1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/fahrenheit" >
        </RadioButton>
    </RadioGroup>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/calc" 
        android:onClick="myClickHandler">
    </Button>

</LinearLayout> 

4.2. State Drawables

State drawables allow to define states. For each state a different drawable can get assigned to the View. For example the following defines different drawables for a button depending on its state.

<?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" />
  <item android:drawable="@drawable/button_checked"
    android:state_checked="true" />
  <item android:drawable="@drawable/button_default" />

</selector> 

4.3. Transition Drawables

Transition Drawables allow to define transitions which can be triggered in the coding.

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/first_image" />
  <item android:drawable="@drawable/second_image" />
</transition> 

final ImageView image = (ImageView) findViewById(R.id.image);
final ToggleButton button = (ToggleButton) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(final View v) {
    TransitionDrawable drawable = (TransitionDrawable) image.getDrawable();
    if (button.isChecked()) {
      drawable.startTransition(500);
    } else {
      drawable.reverseTransition(500);
    }
  }
}); 

5. Vector drawables

Android 5.0 includes the possibility to define vector drawables, similar to svg files but with a limited scope. The following listing demonstrates its usage in the vectordrawable.xml file. Using vector drawables has the advantages that this drawables automatically scale to the density of the device.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="64dp"
     android:width="64dp"
     android:viewportHeight="600"
     android:viewportWidth="600" >
     <group
         android:name="rotationGroup"
         android:pivotX="300.0"
         android:pivotY="300.0"
         android:rotation="45.0" >
         <path
             android:name="v"
             android:fillColor="#000000"
             android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
     </group>
 </vector> 

Android 5.0 contains also the AnimatedVectorDrawable which allows to combine vector drawables with animations. See http://blog.sqisland.com/2014/10/first-look-at-animated-vector-drawable.html for several examples.

6. Animation Drawables

You can also define an animation drawables and assign it to a View via the setBackgroundResource() method.

<!-- Animation frames are phase*.png files inside the
 res/drawable/ folder -->
 <animation-list android:id="@+id/selected" android:oneshot="false">
    <item android:drawable="@drawable/phase1" android:duration="400" />
    <item android:drawable="@drawable/phase2" android:duration="400" />
    <item android:drawable="@drawable/phase3" android:duration="400" />
 </animation-list> 

ImageView img = (ImageView)findViewById(R.id.yourid);
img.setBackgroundResource(R.drawable.your_animation_file);

 // Get the AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

 // Start the animation (looped playback by default).
 frameAnimation.start(); 

Alternative you can implement a class which extends Drawable and implements Animatable.

7. 9 Patch Drawables

9 Patch drawables are Drawables which have a one pixel additional border. On the top and left you define the area which should be scaled if the Drawable is to small for the view. This is the stretch area.

Defining the 9 patch Drawable stretch area

On the right and bottom side you define the area where a text should be placed if this Drawable is used on a view which can write text on it, e.g. a Button.

The ADT supplies the draw9patch program in the android-sdk/tools installation folder, which makes it easy to create 9 Patch drawables.

A nice online generator for 9 patch drawables can be found under the following URL: Simple Nine-patch generator.

8. Custom Drawables

You can also create custom Drawable, which can use the Canvas API for their display. For these drawables you can use the full Canvas API to design them to your need.

9. Exercise: Create Custom Drawables

Note

This example is based on a Blog post from Roman Guy.

Create the following Android project called com.vogella.android.drawables.custom based on the Empty Activity template.

Create the following custom Drawable class.

package com.vogella.android.drawables.custom;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;

public class MyRoundCornerDrawable extends Drawable {

  private Paint paint;

  public MyRoundCornerDrawable(Bitmap bitmap) {
    BitmapShader shader;
    shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
        Shader.TileMode.CLAMP);
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(shader);
  }

  @Override
  public void draw(Canvas canvas) {
    int height = getBounds().height();
    int width = getBounds().width();
    RectF rect = new RectF(0.0f, 0.0f, width, height);
    canvas.drawRoundRect(rect, 30, 30, paint);
  }

  @Override
  public void setAlpha(int alpha) {
    paint.setAlpha(alpha);
  }

  @Override
  public void setColorFilter(ColorFilter cf) {
    paint.setColorFilter(cf);
  }

  @Override
  public int getOpacity() {
    return PixelFormat.TRANSLUCENT;
  }

} 

To use it change your layout file to the following.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:contentDescription="TODO" />

</RelativeLayout> 

Change your MainActivity class to the following. The code assumes that you have a bitmap in your drawable folder called dog.png.

package com.vogella.android.drawables.custom;

import java.io.InputStream;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ImageView button = (ImageView) findViewById(R.id.image);
    InputStream resource = getResources().openRawResource(R.drawable.dog);
    Bitmap bitmap = BitmapFactory.decodeStream(resource);
    button.setBackground(new MyRoundCornerDrawable(bitmap));
  }

} 

10. Support this website

This tutorial is Open Content under the CC BY-NC-SA 3.0 DE license. Source code in this tutorial is distributed under the Eclipse Public License. See the vogella License page for details on the terms of reuse.

Writing and updating these tutorials is a lot of work. If this free community service was helpful, you can support the cause by giving a tip as well as reporting typos and factual errors.

10.1. Thank you

Please consider a contribution if this article helped you. It will help to maintain our content and our Open Source activities.

10.2. Questions and Discussion

If you find errors in this tutorial, please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ as I don't respond to questions already answered there.

11. Links and Literature

11.1. Source Code

Source Code of Examples

11.2. Android Widget Resources

Example Widget from Android API demos

Wiktionary Example Widget

http://code.google.com/p/wiktionary-android/source/browse/trunk/Wiktionary/src/com/example/android/wiktionary/

11.4. vogella Resources

vogella Training Android and Eclipse Training from the vogella team

Android Tutorial Introduction to Android Programming

GWT Tutorial Program in Java, compile to JavaScript and HTML

Eclipse RCP Tutorial Create native applications in Java

JUnit Tutorial Test your application

Git Tutorial Put all your files in a distributed version control system