Tuesday, February 21, 2012

How to Create Custom Dialog in Android?


Step 1: Design the Custom Dialog Layout

First you need to design the content of your custom dialog in a layout resource file. In this case, our custom layout will be a password confirmation dialog, which means we will need twoEditText controls for inputting the password. We will also want some other text controls for labels and the like.
Create a layout resource called /res/layout/password_dialog.xml. The contents of this resource file are shown below:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:id="@+id/root"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/TextView_Pwd1"
        android:text="@string/settings_password"
        android:textStyle="bold" />
    <EditText
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/EditText_Pwd1"
        android:inputType="textPassword" />
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/TextView_Pwd2"
        android:text="@string/settings_password2"
        android:textStyle="bold" />
    <EditText
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/EditText_Pwd2"
        android:inputType="textPassword" />
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/TextView_PwdProblem"
        android:textStyle="bold"
        android:gravity="center" />
</LinearLayout>




This simple layout file relies upon a few other string resources you’ll need to define (labels, see the full source code for details if you need help defining string resources) as well as theEditText input type attribute called textPassword, which masks the password as it is typed into the control. This figure shows what the layout design looks like:


Step 2: Define a New Password Dialog within your Activity Class

Now let’s add the new Dialog to your basic Activity class.
Begin by editing your Activity class and adding the following class member variable:
private static final int MY_PASSWORD_DIALOG_ID = 4;


This defines a unique Dialog identifier for our Activity class. The value is an arbitrary number, but needs to be unique within the Activity.

Step 3: Inflate the Custom Dialog Layout

To create Dialog instances, you must provide a case for your custom password confirmation dialog in the onCreateDialog() method of your Activity class. When the showDialog() method is called, it triggers a call to this method, which must return the appropriate Dialog instance. Therefore, we begin the specific case statement for your new Dialog within the onCreateDialog()method here by inflating our custom layout file that was designed in the previous step and retrieving the important controls we will want to interact with from within it using the findViewById()method.
case MY_PASSWORD_DIALOG_ID:
       LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
       final View layout = inflater.inflate(R.layout.password_dialog, (ViewGroup) findViewById(R.id.root));
       final EditText password1 = (EditText) layout.findViewById(R.id.EditText_Pwd1);
       final EditText password2 = (EditText) layout.findViewById(R.id.EditText_Pwd2);
       final TextView error = (TextView) layout.findViewById(R.id.TextView_PwdProblem);
 
       // TODO: Create Dialog here and return it (see subsequent steps)
As you can see, we grab the two EditText controls that will store the password data, as well as the TextView control where we can display the password error text (passwords either match or do not match).

Step 4: Implement the Password TextWatcher

The next step of our onCreateDialog() case statement implementation for the custom dialog is to register a TextWatcher on the second EditText control so that we can listen for and detect password matches as the user types in order to display the proper string text in the error TextView control (matches/does not match).
Here’s the implementation of the TextWatcher, which is assigned to the second password EditText control using the addTextChangedListener() method.


password2.addTextChangedListener(new TextWatcher() {
   public void afterTextChanged(Editable s) {
      String strPass1 = password1.getText().toString();
      String strPass2 = password2.getText().toString();
      if (strPass1.equals(strPass2)) {
         error.setText(R.string.settings_pwd_equal);
      } else {
         error.setText(R.string.settings_pwd_not_equal);
      }
   }
 
   public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
   public void onTextChanged(CharSequence s, int start, int before, int count) {}
 });






The TextWatcher has three callback methods, but we’re really only interested in the afterTextChanged() method implementation. Here we check the text of the two EditText controls, compare them, and set the error text in the TextView. Here is what the TextWatcher might show when the passwords match:


Step 5: Use the Dialog Builder to Configure the Dialog

The next step of our onCreateDialog() case statement implementation for the custom password confirmation dialog is to use the AlertDialog.Builder class to begin to configure the dialog settings.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Enter Password");
builder.setView(layout);


We set the title of the dialog using the setTitle() method, but the most important thing we do here is use the setView() method to attach our custom layout we just inflated to the dialog. This is how we modify the controls used within our dialog, making it have custom display and developer-defined behavior.

Step 6: Set the Positive and Negative Button Handlers for the Custom Password Dialog

Next, we need to configure the positive and negative buttons associated with our dialog. Recall that dialogs will be reused if displayed more than once. With our password confirmation dialog, we want to make sure to forcefully remove the dialog from the Activity’s dialog pool so that it cannot be reused. We do not want any residual password information being stored after our password dialog is dismissed, whether it is confirmed or dismissed.
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int whichButton) {
      removeDialog(MY_PASSWORD_DIALOG_ID);
   }
});
 
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int which) {
      String strPassword1 = password1.getText().toString();
      String strPassword2 = password2.getText().toString();
      if (strPassword1.equals(strPassword2)) {
         Toast.makeText(SuperSimpleDialogsActivity.this,
            "Matching passwords="+strPassword2, Toast.LENGTH_SHORT).show();
      }
      removeDialog(MY_PASSWORD_DIALOG_ID);
   }
});


We get rid of the dialog in both the negative and positive button click handlers using the removeDialog() method. However, in the positive button handler, we also retrieve the contents of theEditText controls and, if they match, display the password as a Toast message. In most cases, you would not use a Toast, but would save off the password using the method of your choice (preferences, etc.).

Step 7: Generate the Custom AlertDialog from the Builder

Your dialog is completely configured. Now use the create() method of the AlertDialog.Builder class to generate the appropriate AlertDialog and return it, thus ending your case statement for this dialog within the onCreateDialog() method of the Activity class.


AlertDialog passwordDialog = builder.create();
return passwordDialog;


Step 8: Triggering the Password Confirmation Dialog to Display

Finally, you are ready to trigger your password confirmation dialog to display as required. For example, you might add another Button control to your Activity’s screen to trigger your dialog to display. Its click handler might look something like this:
public void onPasswordDialogButtonClick(View v) {
    showDialog(MY_PASSWORD_DIALOG_ID);
}


1 comment: