Home > Android, regular > Android: Dialog box tutorial

Android: Dialog box tutorial


Hi folks,

There’s a lot that’s been written about the evils of dialog boxes , those little boxes that pop up to ask you how whether you’re sure you want to do action X, or provide some information Y.  The real issue with most of these dialog boxes is that they block the user interface, stealing the attention of the user, and disallowing him to deal with what he was doing until he deals with this interruption.

I agree that they are overused and often can be eliminated entirely.  For instance, instead of popping up a dialog box asking whether you’re sure you want to delete something, just do the deletion and provide a mechanism for them to undo their mistake.  Gmail does this well; the problem is that in general it’s much more difficult to provide an undo mechanism than it is to shove a dialog in the user’s face, make him choose an option he might not fully understand, and then absolve oneself of the consequences when he deletes something he didn’t intend to.

Philosophical debate aside, it’s still useful to be able to use a dialog box in a pinch.  I will step through the code to illustrate how to do so in Android.

Android provides a useful Builder implementation for Dialogs.  I’ll write a post about the niceness of the Builder design pattern eventually, but suffice to say, they allow a nice mechanism for specifying optional arguments rather than having dozens of overloaded constructors that take in various arguments.  When all the arguments have been provided to the Builder through a series of chained method invocations, you convert the Builder object into the object it creates through a final create() command.

The class used to create dialog windows is AlertDialog while the builder object I mentioned earlier is AlertDialog.Builder .  Because the dialog will be displayed on the screen, we need to provide the builder object with the Context in which it should render itself.

AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
builder.setIcon(R.drawable.dialog_question);
builder.setTitle("Title");
builder.setInverseBackgroundForced(true);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
    dialog.dismiss();
  }
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
    dialog.dismiss();
  }
});
AlertDialog alert = builder.create();
alert.show();

This is the basic code you need to create a dialog box that pops up, has yes and no option, and dismisses itself gracefully when either of those two options are clicked.

Now, if you’re used to Java’s swing dialog boxes, you might be surprised to see the listeners attached to the buttons in the setNegativeButton and setPositiveButton methods  In Swing, the dialog blocks all other tasks until the dialog is dismissed; as such it’s sufficient to check the return code of the dialog, and then take action based on that value.  That doesn’t fit into the Android paradigm, however, because at all times the app must be responsive and able to be interrupted by an incoming phone call or text message, for instance.  Thus the need for the asynchronous button listeners.

This complicates things somewhat; how do I perform business logic within the context of the dialog?  How do I get handles to the object or objects on which I need to perform actions?  Unlike some other languages, one cannot pass methods as objects in Java.  As such, we should use a Function Object to the dialog, said object encapsulating the business logic that must happen when a button is pressed.

I choose to implement my function object with the Command design pattern; the source of my Command interface is as follows:

/**
 * Functor object that allows us to execute arbitrary code.
 *
 * This is used in conjunction with dialog boxes to allow us to execute any
 * actions we like when a button is pressed in a dialog box (dialog boxes
 * are no longer blocking, meaning we need to register listeners for the various
 * buttons of the dialog instead of waiting for the result)
 *
 * @author NDUNN
 *
 */
public interface Command {
	public void execute();

	public static final Command NO_OP = new Command() { public void execute() {} };
}

I provide a wrapper around the Command object in order to make the API easier to make the dialog boxes.

public static class CommandWrapper implements DialogInterface.OnClickListener {
  private Command command;
  public CommandWrapper(Command command) {
    this.command = command;
  }

  @Override
  public void onClick(DialogInterface dialog, int which) {
    dialog.dismiss();
    command.execute();
  }
}

Combining this with a variation of the earlier code, we have a general purpose method that returns a Dialog confirming whether we want to delete something.

private static final CommandWrapper DISMISS = new CommandWrapper(Command.NO_OP);

public static AlertDialog createDeletionDialog(final Context context,
    final String name, final Command deleteCommand) {

  AlertDialog.Builder builder = new AlertDialog.Builder(context);
  builder.setCancelable(true);
  builder.setIcon(R.drawable.dialog_question);
  builder.setTitle("Are you sure you want to delete \"" + name + "\"?");
  builder.setInverseBackgroundForced(true);
  builder.setPositiveButton("Yes", new CommandWrapper(deleteCommand));
  builder.setNegativeButton("No", DISMISS);
  return builder.create();
}

Here is this method used in context:

// When the delete button is clicked, a dialog pops up confirming
deleteButton.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    Command delete = new Command() {
      public void execute() {
        deleteFromDatabase(personID);
      }
    };
    AlertDialog deletionDialog = DialogUtils.createDeletionDialog(ShowPlaceActivity.this, personName, delete);
    deletionDialog.show();
  }
});

In conclusion, you’ve seen how Android provides a nice Builder interface for creating dialogs, and how these dialogs differ from those of Java. Furthermore, you’ve seen how the Command design pattern can encapsulate business logic and be executed the instant a button is pressed.

About these ads
Categories: Android, regular Tags: , ,
  1. SkyDiver
    September 18, 2010 at 5:46 am

    How come nobody commented on this yet?

    Excelllllent tutorial!!!!

    Thanks!!!

    • i82much
      September 18, 2010 at 11:29 am

      Thanks – I appreciate feedback on my articles. Any other Android topics you’d like me to write about?

  2. ChristianKl
    September 20, 2010 at 7:29 am

    The code doesn’t compile in that form.
    1) It’s an interface instead of overriding
    2) Closing parenthesis are lacking.
    3) It’s not clear what I have to save under R.drawable.dialog_question.

    • i82much
      September 20, 2010 at 8:49 am

      1) has to do with whether you are compiling for 1.5 or 1.6 compliance. 1.6 compliance will allow you to use @Override on interfaces

      I’ll fix the rest tonight. Thanks for the heads up

      • i82much
        September 20, 2010 at 7:33 pm

        2) Where? I looked through and didn’t see mismatched parens
        3) You don’t save anything under R.drawable.dialog_question – that’s a built in image that the OS provides. If you wish to use a different icon in the dialog, put in a different reference to a resource.

    • i82much
      October 1, 2010 at 1:14 pm

      I fixed the missing closing parenthesis. Thanks for bringing that to my attention.

  3. ChristianKl
    September 20, 2010 at 8:30 am

    If you are searching for ideas I would be interested in articles explaining the behavior of the softkeyboard.

  4. Ankit
    October 3, 2010 at 11:27 pm

    nice topic…simple to understand….let me know can we do divert(merging of two calls )in android…i can picked one and can dialled second call but unable to make conference of these two…..

  5. Chris
    October 14, 2010 at 4:06 pm

    Wow, great post, but have you ever considered this:

    http://thelure.wordpress.com/2010/10/14/nick-dunn-is-a-credulous-tool/

  6. Blueguy
    October 28, 2010 at 5:19 pm

    Man that was awsome,it helped me a lot ,thanxxxxxxxxxxx

  7. Sawny
    October 15, 2011 at 6:33 am

    Don’t get it, how do I use this?

    Can you prov a sample code and an full example?

    I.e. // When the delete button is clicked, a dialog pops up confirming
    deleteButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    Command delete = new Command() {
    public void execute() {
    deleteFromDatabase(personID);
    }
    };
    AlertDialog deletionDialog = DialogUtils.createDeletionDialog(ShowPlaceActivity.this, personName, delete);
    deletionDialog.show();
    }
    });

    where do you get the personID variable?
    Is this code in the same file as the other CommandWrapper code?

  8. Aamirkhan
    October 21, 2011 at 11:56 pm

    how can i show image after click to dialog box?

  9. DaveG
    January 15, 2012 at 9:10 am

    Simply Brilliant, Works like a charm. I have been looking for something like this for a while. Thank You so much.

  10. Ashutosh
    February 3, 2012 at 5:58 am

    Thanks a ton……………. :-)

  11. Eric
    February 17, 2012 at 6:29 am

    Had to change some things about your code to get it to work for me on ICS, but thanks a ton. For some reason, even after copying code from developer.android.com on how to implement dialogs, my app was crashing ever time I tried to show the dialog…despite it creating just fine. Your code (after altered to run) works great. I made my own libs to deal with this in a general case. Lifesaver!

  12. ken
    February 18, 2012 at 11:17 am

    can some help me with my app i am trying to open a dialog box.open by image button cant get my head round this thanks

  13. Ahad nawaz
    February 24, 2012 at 2:32 am

    This is awesome solution, but you haven’t specify the place of each block of code.
    I mean one could not adjust the code in appropriate classes.

    • dmi
      February 28, 2012 at 10:49 am

      I use your code. It’s great. Thank you

      I made a class (DialogResult) which encapsulates all that. If it can help someone ?

      /**
      *
      * Example of call in an activity “MyActivity”
      * ————————————————————–
      *
      */

      private void test_ok() {

      DialogResult.Command OKCommand = new DialogResult.Command() {
      @Override
      public void execute() { Log.d(“”,”OK”); }
      };

      DialogResult.show(this,”is it OK ? “, OKCommand);

      }

      // test with 2 different actions when pressing yes or No

      private void test_yes_no() {

      DialogResult.Command yesCommand = new DialogResult.Command() {
      @Override
      public void execute() { Log.d(“”,”YES”); }
      };

      DialogResult.Command noCommand = new DialogResult.Command() {
      @Override
      public void execute() { Log.d(“”,”NO”); }
      };

      DialogResult.show(this,”yes or no ? “, yesCommand, noCommand );

      }

      // The class DialogResult which encapsulate DialogResult Patern

      //——————– DialogResult.java ——————————————–

      import android.app.AlertDialog;
      import android.content.Context;
      import android.content.DialogInterface;

      public class DialogResult {

      public interface Command {

      public void execute();

      public static final Command No_Operation = new Command() {
      public void execute() {
      }
      };
      }

      public static class CommandWrapper implements DialogInterface.OnClickListener {

      private Command command;

      public CommandWrapper(Command command) {
      this.command = command;
      }

      @Override
      public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss();
      command.execute();
      }
      }

      private static final CommandWrapper DISMISS = new CommandWrapper(Command.No_Operation);

      public static AlertDialog createDialog(final Context context,
      final String msg, final Command yesCommand, final Command noCommand) {

      AlertDialog.Builder builder = new AlertDialog.Builder(context);
      builder.setCancelable(true);
      //builder.setIcon(R.drawable.dialog_question);
      builder.setTitle(msg);
      builder.setInverseBackgroundForced(true);
      builder.setPositiveButton(“Oui”, new CommandWrapper(yesCommand));
      builder.setNegativeButton(“Non”, new CommandWrapper(noCommand));
      return builder.create();
      }

      public static void show(final Context context,final String msg, final Command OKCommand)
      {
      DialogResult.createDialog(context,msg,OKCommand,Command.No_Operation).show();
      }

      public static void show(final Context context,final String msg, final Command yesCommand, final Command noCommand)
      {
      DialogResult.createDialog(context,msg,yesCommand,noCommand).show();
      }

      }

  14. Gremlin1708
    April 18, 2012 at 11:49 am

    WOW… This was really helpful for a beginner like me. Looked like chinese to me in the beginning but i figured it out. Very nice.

    Thank you.

  15. dana de cooper
    September 24, 2012 at 9:52 pm

    nice tutorial …its very helpful for the newbie…all the best

  16. November 8, 2012 at 10:06 pm

    as a beginner like me good tutorial to follow.. hope u post more like this.. thanks a lot :)

  17. Giancarlo Leonio
    March 13, 2013 at 4:24 pm

    Hi Nick, thanks for this helpful dialog box tutorial! I compiled a list of some top resources on customizing dialog boxes in android. I included your post. Check it out/ feel free to share. http://www.verious.com/board/Giancarlo-Leonio/customizing-dialog-boxes-in-android/ Hope this can be useful to other developers too.

  1. May 23, 2012 at 10:53 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: