Home > android, ui > Customizing AlertDialog

Customizing AlertDialog

Android has two ways to create dialogs: for simple ones, there is AlertDialog and its builder, for more complex there is Dialog. AlertDialog looks very nice: the bottom panel (for buttons) is highlighted, the title bar has an icon, the font sizes are just right. But at the same time, AlertDialog can be too restrictive. You can replace the content view and configure the buttons, but you can’t change the logic of how these buttons work, and you can’t get to individual UI components to modify their behavior. Or so I thought. Whenever I needed a dialog with some logic to it (such as disabling buttons until the user provides correct input), I used to use plain Dialog. It did what I needed, but my dialogs looked different than AlertDialog, as you can see in the Android Development Guide. The resources that Android uses for AlertDialog are: 1) private, and can’t be referenced directly from an application using “@android:drawable/imgname” and 2) can be customized by the hardware vendors (my Samsung Galaxy S uses a bluish scheme and a different title bar icon). For those two reasons, I had to find a way to customize AlertDialog without trying to copy those resources into my project and rebuild the way the UI looks with my own code.

Sidebar: I’m really not too happy with how some Andorid resources can’t be referenced from an application. Especially menu icons: for example, ic_menu_close_clear_cancel and ic_menu_add are accessible under “@drawable:android”, but ic_menu_refresh, or ic_menu_attachment are private and have to be copied into the project. The trouble, of course, is that hardware manufacturers can customize those, and your application will look inconsistent).

Ok, so it turns out, you can subclass AlertDialog, and get all the benefits with respect to its appearance, and still implement the behavior logic as needed.

public class MyPrettyDialog extends AlertDialog {

	private ListView mListView;
	private MyAdapter mAdapter;
	private Button mAcceptButton;

	public MyPrettyDialog(Context context) {
		super(context);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		ListView listView = new ListView(mContext);
		listView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT, 1.0f));
		listView.setId(android.R.id.list);

		MyAdapter adapter = new MyAdapter();

		listView.setAdapter(adapter);
		listView.setOnItemClickListener(adapter);

		mListView = listView;
		mAdapter = adapter;

		setInverseBackgroundForced(true);
		setView(listView);
		setTitle(R.string.mytitle);
		setCancelable(false);

		setButton(DialogInterface.BUTTON_POSITIVE, "Positive",
				new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// This is replaced later
					}
				});

		setButton(DialogInterface.BUTTON_NEGATIVE, "Negative",
				new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// Do something
					}
				});

		super.onCreate(savedInstanceState);

		/*
		 * Replace the click listener
		 */
		mAcceptButton = getButton(BUTTON_POSITIVE);
		mAcceptButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// Do something, the dialog is NOT closed automatically
			}
		});
	}
}

The most important part here is the overriden onCreate(). It is called automatically by the framework as nedded (just like for Activities). Creating this dialog is as simple as when using AlertDialog.Builder:

	@Override
	protected Dialog onCreateDialog(int id) {
		if (id == MY_PRETTY_DIALOG) {
			MyPrettyDialog dialog = new MyPrettyDialog(this);
			return dialog;
		}
		return super.onCreateDialog(id);
	}

The real value of the above code is that we can get references to UI widgets and keep them in the dialog (mListView, mAcceptButton). With this, we can for example disable the “Accept” button until the user provides required data. Also, AlertDialog, by default, closes right after the user clicks any of the buttons, and you can’t avoid that. If you would like to do some validation (keeping the “Accept” button enabled, and explaining to the user what he needs to fill in and how), you can do that by replacing the click handler by the button with your own, as the code above does at the end of onCreate. And this is what I actually ended up with – an AlertDialog with pretty involved processing logic, that still has the look the users expect.

Advertisements
Categories: android, ui
  1. rekanter
    May 20, 2015 at 5:16 pm

    no, doesn’t work for me
    the background of the dialog is transparent and the buttons are missing
    where does the code snippet onCreateDialog() come from?
    Are you using the Builder with this class? Then can you add this code too, please?
    That’s why I asked for a complete project. 🙂

  2. rekanter
    May 18, 2015 at 11:52 pm

    can you link to the source code please?

    • May 19, 2015 at 1:05 am

      Um, that was soooo long ago 🙂 The sample code is there, just above…?

  3. Julie
    November 9, 2011 at 10:13 am

    Hello, I am building my customized AlertDialog with fields for user input in a similar way. However, in my activity I created a button with onclicklistener to instantiate CustomizedDialog:

    CustomizedDialog.Builder builder = new CustomizedDialog.Builder(context);

    and I found my dialog is not created; if i use:
    onCreateDialog(int) here, I’ll receive exceptions.

    Do you know any reasons? any help is highly appreciated!

    • November 9, 2011 at 11:16 am

      In my code, I don’t customize Builder at all – rather, I subclass AlertDialog and instantiate the UI inside onCreate. As for exceptions, check the logcat, and fix them 🙂

  4. Jonas Petersson
    February 27, 2011 at 1:22 am

    Привет Костя,
    I agree this is a neat trick, but there is one trick I’ve failed ot manage with AlertDialog: Removing the title – sure I can make it not show up, but it will still take up the same space. So for those cases I suspect I’m still forced to use the pure Dialog, right? On a related subject, did you see my post concerning Dialog being somewhat broken in 3.0?
    http://code.google.com/p/android/issues/detail?id=14981
    It’s no HUGE deal, but the way it used to work was very neat. I’m hoping this is a typical x.0 issue similar to the 2.0/2.01 nits that were fixed reasonably fast, but having no comment at all on it is somewhat worrying – perhaps I should have used harsher words…

  1. February 27, 2011 at 1:14 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