Android Custom Dialogs For User Input

rocksaucestudios on 4.29.2011 in Development

Android development takes a bit of time to wrap your head around, especially if you are more familiar with Windows or iOS programming and using delegates instead of anonymous classes. I was recently tasked with creating some custom dialogs to capture specific user input and wanted to do so in a way that would encapsulate all the dialog configuration and data retrieval. I wanted a nice black box where I could supply the necessary default information and easily retrieve the results. To do this I created a simple base class that all my dialogs would use.


public abstract class BaseDialog implements DialogInterface.OnClickListener
{
	public interface OnDismissListener
	{
		public void onDialogDismissed(BaseDialog dialog);
	}

	protected AlertDialog.Builder m_Builder;
	protected Context m_Context;
	protected OnDismissListener m_DismissListener; 

	public int RequestCode = 0;
	public String TitleText = "Dialog";
	public String AcceptText = "Accept";
	public String CancelText = "Cancel";
	public boolean DidAccept = false;

	protected BaseDialog(Context context, int requestCode, OnDismissListener dismissListener)
	{
		this.m_Builder = new AlertDialog.Builder(context);
		this.m_Context = context;
		this.m_DismissListener = dismissListener;
		this.RequestCode = requestCode;
	}

	protected void prepareDialog()
	{
		this.m_Builder.setTitle(this.TitleText);
		this.m_Builder.setPositiveButton(AcceptText, this);
		this.m_Builder.setNegativeButton(CancelText, this);
	}

	public void show()
	{
		this.prepareDialog();
		AlertDialog dialog = this.m_Builder.create();
		this.onCreate(dialog);
		dialog.show();
	}

	protected void onCreate(AlertDialog dialog)
	{
	}

	@Override
	public void onClick(DialogInterface dialog, int buttonId)
	{
		switch(buttonId)
		{
			case DialogInterface.BUTTON_POSITIVE:
				this.DidAccept = true;
			case DialogInterface.BUTTON_NEGATIVE:
				{
					dialog.dismiss();
					if (this.m_DismissListener != null)
					{
						this.m_DismissListener.onDialogDismissed(this);
					}
				} break;
			default:
				break;
		}
	}
}

 

  • OnDismissListener: You can create an anonymous class to retrieve the results of the dialog after it is dismissed via a dialog button press.
    I prefer not to use anonymous classes, so I will make the Activity calling the dialog implement this interface and a switch case on the Request Code to determine the dialog dismissed.
  • RequestCode: Set this code to uniquely identify this dialog in your Activity when the OnDismissListener is called.
  • prepareDialog: This function is automatically called before the dialog is shown and is used to provide the AlertDialog.Builder the necessary data for the dialog.
  • show: This is called from the Activity after all the necessary setup has been completed.
  • onCreate: This method can be overridden to do further alterations to the dialog after it has ben created, but before it has been shown.
  • onClick: This method will handle the button click events of the dialog buttons or default lists.

 

Below is an example of extending the BaseDialog and uses a List in Single Choice Mode.

Single Choice Dialog


public class SingleChoiceDialog extends BaseDialog
{
	public String[] Options;
	public int SelectedOption = -1;

	public SingleChoiceDialog(Activity activity, int requestCode, OnDismissListener dismissListener)
	{
		super(activity, requestCode, dismissListener);
	}

	@Override
	protected void prepareDialog()
	{
		super.prepareDialog();
		this.m_Builder.setSingleChoiceItems(this.Options, this.SelectedOption, this);
	}

	@Override
	public void onClick(DialogInterface dialog, int buttonId)
	{
		if (buttonId >= 0)
		{
			this.SelectedOption = buttonId;
		}
		else
		{
			super.onClick(dialog, buttonId);
		}
	}
}

 

In the onClick method is overridden to record the currently selected option or to call the parent onClick if a button is clicked.

 

The next example uses a custom layout to show an EditText view in the dialog.

Edit Text Dialog


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:background="@android:drawable/screen_background_light"
	android:padding="5dip"
	android:gravity="center_vertical|center_horizontal"
>
	<EditText android:id="@+id/Dialog_EditText_Text"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:layout_gravity="center_vertical|center_horizontal"
	/>
&lt/LinearLayout>

public class EditTextDialog extends BaseDialog
{
	private EditText m_EditText;

	public String Text = "";

	public EditTextDialog(Activity activity, int requestCode, OnDismissListener dismissListener)
	{
		super(activity, requestCode, dismissListener);
	}

	@Override
	protected void onCreate(AlertDialog dialog)
	{
		LayoutInflater inflator = (LayoutInflater)this.m_Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View view = inflator.inflate(R.layout.dialog_edittext, null);

		this.m_EditText = (EditText)view.findViewById(R.id.Dialog_EditText_Text);
		this.m_EditText.setText(this.DefaultText);
		this.m_EditText.setOnFocusChangeListener(this);

		dialog.setView(view, 0, 0, 0, 0);	
	}

	@Override
	public void onClick(DialogInterface dialog, int buttonId)
	{
		this.Text = this.m_EditText.getText().toString();
		super.onClick(dialog, buttonId);
	}
}

 

This time the onCreate method is overridden to inflate the layout and set the view. This can also be done during the prepareDialog stage, but if you are using a non-default background a margin will be present.

Next I have shown how to set up the dialogs and an example of having the Activity implement the OnDismissListener to capture the dialog results.

 


private static final int DIALOG_EDITTEXT	= 0x0000;
private static final int DIALOG_SINGLECHOICE	= 0x0001;

private String[] m_SingleChoiceOptions = {"Option 1", "Option 2", "Option 3", "Option 4"};

@Override
public void onClick(View view)
{
	switch(view.getId())
	{
		case R.id.button_testTextDialog:
			{
				EditTextDialog dialog = new EditTextDialog(this, DIALOG_EDITTEXT, this);
				dialog.TitleText = "Test";
				dialog.DefaultText = "Enter Text here";
				dialog.show();
			} break;
		case R.id.button_testSingleChoiceDialog:
			{
				SingleChoiceDialog dialog = new SingleChoiceDialog(this, DIALOG_SINGLECHOICE, this);
				dialog.TitleText = "Test";
				dialog.Options = m_SingleChoiceOptions;
				dialog.SelectedOption = 2;
				dialog.show();
			} break;
	}
}

@Override
public void onDialogDismissed(BaseDialog dialog)
{
	if (!dialog.DidAccept)
	{
		return;
	}

	switch (dialog.RequestCode)
	{
		case DIALOG_EDITTEXT:
			{
				EditTextDialog editTextDialog = (EditTextDialog)dialog;
				this.m_TestTextDialogText.setText(editTextDialog.Text);
			} break;
		case DIALOG_SINGLECHOICE:
			{
				SingleChoiceDialog singleChoiceDialog = (SingleChoiceDialog)dialog;
				this.m_TestSingleChoiceDialogText.setText(this.m_SingleChoiceOptions[singleChoiceDialog.SelectedOption]);
			} break;
	}
}

 

This makes the Activity much less convoluted and easier to quickly glance over the code. Multiple dialogs are also much more manageable now. From here there is no limit on the complexity of the dialog. Below are screenshots of two more examples, which should be easy to recreate using the examples from above.

Multiple Choice Dialog Numeric Dialog

Comments

comments

Areas of Expertise

Contributors