Android Drawables in Kotlin XML: A Comprehensive Guide for UI Design

In Android development, Drawables are a crucial resource type used to define graphic assets. These assets are employed in the UI for backgrounds, images, icons, and more. Android Drawables can be defined in XML or programmatically in Kotlin, and understanding how to effectively use them is essential for creating visually appealing and performant apps. This blog post will introduce you to Android Drawables in Kotlin XML development, providing you with comprehensive knowledge and practical examples to elevate your Android UI design skills.

What are Android Drawables?

Android Drawables are graphic resources that can be used to describe shapes, colors, images, patterns, and animations. They are used extensively in Android apps to:

  • Define backgrounds for views (e.g., buttons, layouts).
  • Display images or icons.
  • Create custom UI elements using shape and state definitions.
  • Add animations through animation drawables.

Android supports a variety of Drawable types, including:

  • Bitmap Drawables: Based on raster image formats like PNG, JPG, and WebP.
  • Vector Drawables: Defined using XML-based vector graphics, ideal for resolution independence.
  • Shape Drawables: Defined using XML to draw geometric shapes.
  • Layer List Drawables: Stack multiple drawables on top of each other.
  • State List Drawables: Change the drawable based on the state of the view (e.g., pressed, focused).
  • Transition Drawables: Animate between two drawables.
  • Inset Drawables: Apply insets to another drawable.
  • Clip Drawables: Clip another drawable based on its current level.
  • Scale Drawables: Scale another drawable based on its current level.

Why Use Android Drawables?

Using Android Drawables provides several benefits:

  • Performance: Properly optimized drawables improve app performance.
  • Resolution Independence: Vector drawables scale without losing quality on different screen densities.
  • Themability: Drawables can adapt to different themes, providing a consistent UI across the app.
  • Reusability: Define drawables once and use them in multiple places.

Implementing Drawables in XML with Kotlin Examples

The most common way to define drawables in Android is using XML files, which are then referenced in Kotlin code. Below are several examples to get you started.

1. Bitmap Drawable

Bitmap Drawables are the simplest type, allowing you to display raster images.

Step 1: Add Image to Drawable Folder

First, add your image (e.g., my_image.png) to the res/drawable/ folder. If you have different densities, place the appropriate images in folders like res/drawable-hdpi/, res/drawable-mdpi/, etc.

Step 2: Define Drawable XML

Create a drawable XML file (e.g., res/drawable/bitmap_drawable.xml):


<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/my_image"
    android:gravity="center" />

Explanation:

  • <bitmap> is the root element, indicating a bitmap drawable.
  • android:src points to the image resource.
  • android:gravity defines how the bitmap should be positioned within its container.
Step 3: Use in Layout XML or Kotlin Code

In Layout XML:


<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/bitmap_drawable" />

In Kotlin Code:


val imageView: ImageView = findViewById(R.id.imageView)
imageView.setImageResource(R.drawable.bitmap_drawable)

2. Vector Drawable

Vector Drawables use XML to define vector graphics, making them ideal for resolution-independent icons and shapes.

Step 1: Create Vector Asset

Right-click on the res/drawable/ folder in Android Studio, select “New” -> “Vector Asset”, and choose an icon from the Material Design icons or import an SVG.

Step 2: Modify Vector Drawable XML (if needed)

The generated XML (e.g., res/drawable/ic_vector.xml) looks something like this:


<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#FF000000"
        android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10,-4.48,10,-10S17.52,2,12,2z" />
</vector>

Explanation:

  • <vector> is the root element.
  • android:width and android:height define the intrinsic size of the drawable.
  • android:viewportWidth and android:viewportHeight define the coordinate system for the vector.
  • <path> elements define the shapes to draw.
Step 3: Use in Layout XML or Kotlin Code

In Layout XML:


<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_vector" />

In Kotlin Code:


val imageView: ImageView = findViewById(R.id.imageView)
imageView.setImageResource(R.drawable.ic_vector)

3. Shape Drawable

Shape Drawables allow you to define geometric shapes using XML.

Step 1: Create Shape Drawable XML

Create a new XML file in res/drawable/ (e.g., res/drawable/shape_drawable.xml):


<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#4CAF50" />
    <corners android:radius="8dp" />
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp" />
</shape>

Explanation:

  • <shape> is the root element.
  • android:shape defines the shape type (rectangle, oval, line, ring).
  • <solid> sets the fill color.
  • <corners> sets the corner radius.
  • <padding> sets the padding inside the shape.
Step 2: Use in Layout XML or Kotlin Code

In Layout XML:


<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/shape_drawable"
    android:text="Hello Shape Drawable!" />

In Kotlin Code:


val textView: TextView = findViewById(R.id.textView)
textView.background = ContextCompat.getDrawable(this, R.drawable.shape_drawable)

4. Layer List Drawable

Layer List Drawables allow you to stack multiple drawables on top of each other.

Step 1: Create Layer List Drawable XML

Create a new XML file in res/drawable/ (e.g., res/drawable/layer_list_drawable.xml):


<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#E91E63" />
        </shape>
    </item>
    <item
        android:top="10dp"
        android:left="10dp"
        android:right="10dp"
        android:bottom="10dp">
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF" />
        </shape>
    </item>
</layer-list>

Explanation:

  • <layer-list> is the root element.
  • <item> elements define individual layers. Each layer can contain a drawable.
Step 2: Use in Layout XML or Kotlin Code

In Layout XML:


<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/layer_list_drawable"
    android:text="Hello Layer List Drawable!" />

In Kotlin Code:


val textView: TextView = findViewById(R.id.textView)
textView.background = ContextCompat.getDrawable(this, R.drawable.layer_list_drawable)

5. State List Drawable

State List Drawables change the drawable based on the state of the view (e.g., pressed, focused, enabled).

Step 1: Create State List Drawable XML

Create a new XML file in res/drawable/ (e.g., res/drawable/state_list_drawable.xml):


<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_focused" android:state_focused="true" />
    <item android:drawable="@drawable/button_normal" />
</selector>

Explanation:

  • <selector> is the root element.
  • <item> elements define different states.
  • android:state_pressed, android:state_focused are state attributes.
  • android:drawable specifies the drawable to use for each state.

Note: You’ll need to define button_normal.xml, button_pressed.xml, and button_focused.xml.

Step 2: Use in Layout XML or Kotlin Code

In Layout XML:


<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/state_list_drawable"
    android:text="Click Me!" />

In Kotlin Code:


val button: Button = findViewById(R.id.button)
button.background = ContextCompat.getDrawable(this, R.drawable.state_list_drawable)

Optimizing Drawables for Performance

To ensure optimal performance, follow these tips:

  • Use Vector Drawables for Icons: They scale without losing quality and reduce APK size.
  • Optimize Bitmap Images: Use tools like TinyPNG to compress images.
  • Use WebP Format: WebP provides better compression and quality compared to JPG and PNG.
  • Avoid Large Background Images: Complex and large drawables can slow down UI rendering.
  • Reuse Drawables: Use the same drawable for multiple views to save memory.

Conclusion

Android Drawables are essential resources for designing UIs in Android applications. By using Bitmap, Vector, Shape, Layer List, and State List Drawables effectively in XML, you can create visually appealing, responsive, and performant UIs. Remember to optimize your drawables to improve your app’s overall performance and user experience. With the examples and guidelines provided in this blog post, you are well-equipped to integrate drawables into your Kotlin XML development workflow effectively.