Smartphones

Theming toast messages with the Android SDK

A toast message is a warm and fuzzy way to alert users about what is happening in your Android app without interrupting the UX. Learn how to build custom toast messages.

One very handy feature of the Android UI kit is the toast message class. A toast message is the ideal way to alert the user of what is happening without interrupting the user experience with something as obtrusive as a dialog. For example, let's say the user pressed the Save button. A toast message is the perfect way to give the user a warm and fuzzy when the save completes successfully.

The only issue is the toast message is usually themed at the device level. This means that, if the user is running a version of Android prior to Honeycomb, the toast messages are probably dark-gray and white; in later versions of Android, the toast messages are likely light blue and white. Either way, depending on the color scheme of your Android application, there is a good chance you might end up with an eyesore.

Fortunately, there is hope. The Android platform is famous for its flexibility, and the toast class is no exception. This tutorial will show you everything you need to know to build your own customized toast messages. You can follow along with my step-by-step tutorial or download and import the entire project directly into Eclipse.

1. Using Eclipse create a new Android project. Target version 1.6 or higher of the OS. Rename the startup file to Main.java and the corresponding layout to main.xml.

2. Because I am a fan of grilled cheese, I will adorn my custom toast message with a big wedge of cheddar. In the resource folder I created a new directory called /drawable. Here I placed the custom image I plan to use on my dialogs, cheese.png.

3. Because I want to make sure there is no confusing my custom toast message with the standard system one, I create a bright red gradient to serve as the background for my layout. In the /res directory, add a new folder and call it /xml. In this new folder, I create a file called rounded_rect.xml.

rounded_rect.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
       <gradient
           android:startColor="#ffff0000"
              android:endColor="#ff480000"
              android:angle="270"/>
      <corners
          android:bottomRightRadius="15dp"
          android:bottomLeftRadius="15dp"
             android:topLeftRadius="15dp"
             android:topRightRadius="15dp"/>
</shape>

4. Before we can get down to the business of writing Java code, we still need to layout out our main application and the custom toast. Both of these files get placed in the /res/layout directory.

custom_toast.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/toast_layout"
       android:orientation="vertical"     
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:background="@xml/rounded_rect"
       android:layout_margin="25dip">
       <LinearLayout 
              android:layout_margin="5dip"
              android:orientation="horizontal"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content">
              <ImageView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:src="@drawable/cheese"/>
             <LinearLayout
                    android:orientation="vertical"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:gravity="center">
                    <TextView
                        android:paddingLeft="10dip"
                        android:layout_width="fill_parent"
                        android:layout_height="fill_parent"
                        android:id="@+id/toast_text_1"
                        android:textColor="#ffffff"
                        android:textSize="14sp"
                        android:textStyle="bold"
                        android:gravity="center"/>
            </LinearLayout>
      </LinearLayout>
</LinearLayout>

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#000000">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="#ffffff"
        android:text="Custom Toast Demonstration"
        android:layout_gravity="center"
        android:layout_margin="15dip"/>
    <Button
           android:id="@+id/plain_toast"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:text="Plain Toast"
           android:layout_gravity="center"
           android:layout_margin="10dip"/>
    <Button
           android:id="@+id/cheesy_toast"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:text="Cheesy Toast"
           android:layout_gravity="center"
           android:layout_margin="10dip"/>
</LinearLayout>

5. Now it's time to code up the Main.java file. The on create method makes use of Java's ability to create inline functions, which are responsible for invoking our make toast method. Depending on the parameter passed, the method will either display a standard toast or create a new one and apply our theme to it.

Main.java

package com.authorwjf.cheese_n_toast;

import android.os.Bundle;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class Main extends Activity {
       final static int PLAIN = 01;
       final static int CUSTOM = 02;
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      findViewById(R.id.plain_toast).setOnClickListener(new OnClickListener(){
                   @Override
                   public void onClick(View v) {
                          makeToast(PLAIN);
                   }
        });
        findViewById(R.id.cheesy_toast).setOnClickListener(new OnClickListener(){
                     @Override
                     public void onClick(View v) {
                            makeToast(CUSTOM);
                     }
         });
    }

private void makeToast(int type) {
   if (type==PLAIN) {
          Toast.makeText(getBaseContext(), "This is a standard toast message.", Toast.LENGTH_SHORT).show();
   } else {
          LayoutInflater inflater = getLayoutInflater();
          View layout = inflater.inflate(R.layout.custom_toast, (ViewGroup) findViewById(R.id.toast_layout));
          ((TextView) layout.findViewById(R.id.toast_text_1)).setText("This is a custom toast message.");
          Toast toast = new Toast(getBaseContext());
          toast.setDuration(Toast.LENGTH_SHORT);
          toast.setView(layout);
          toast.show();
    }
  }
}
When you give the application a try on your device or an emulator, you'll see that the difference between a standard toast message (Figure A) and a custom one (Figure B) can be very dramatic! Figure A

Figure B

A side note: I frequently get asked how to set a custom display time for the toast message. For no good reason I know, the UI framework for Android doesn't provide this option at this time. Hopefully a future version of the Android SDK will remedy this shortcoming.

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

0 comments