1. Code
  2. Mobile Development
  3. Android Development

Showing Material Design Dialogs in an Android App

Scroll to top

The material design team at Google defines the functionality of dialogs in Android as follows:

Dialogs inform users about a specific task and may contain critical information, require decisions, or involve multiple tasks.

Now you have understood what dialogs are used for, it's now time to learn how to display them. Want to learn about the kinds of material design dialogs in Android? In this tutorial, I'll take you through the process of showing different kinds of material design dialogs in Android. We'll cover the following dialogs:

  • material design alert
  • single and multiple choice 
  • time and date picker
  • bottom sheet dialog
  • full-screen dialog

It's always helpful to follow an Android dialog example. A sample project for this tutorial can be found on our GitHub repo for you to easily follow along.

1. Alert Dialog

According to the official Google material design alert documentation:

Alerts are urgent interruptions, requiring acknowledgement, that inform the user about a situation.

Creating an Alert Dialog

Make sure you include the latest appcompat artifact in your build.gradle file (app module). The minimum supported API level is Android 4.0 (API level 14). 

1
dependencies {
2
    implementation 'com.android.support:appcompat-v7:26.1.0'
3
}

The next thing is to create an instance of AlertDialog.Builder

1
new AlertDialog.Builder(this)
2
        .setTitle("Nuke planet Jupiter?")
3
        .setMessage("Note that nuking planet Jupiter will destroy everything in there.")
4
        .setPositiveButton("Nuke", new DialogInterface.OnClickListener() {
5
            @Override
6
            public void onClick(DialogInterface dialog, int which) {
7
                Log.d("MainActivity", "Sending atomic bombs to Jupiter");
8
            }
9
        })
10
        .setNegativeButton("Abort", new DialogInterface.OnClickListener() {
11
            @Override
12
            public void onClick(DialogInterface dialog, int which) {
13
                Log.d("MainActivity", "Aborting mission...");
14
            }
15
        })
16
        .show();

Here we created an instance of AlertDialog.Builder and began configuring the instance by calling some setter methods on it. Note that we are using the AlertDialog from the Android support artifact.

1
import android.support.v7.app.AlertDialog;

Here are the details of the setter methods we called on the AlertDialog.Builder instance. 

  • setTitle(): set the text to show in the title bar of the dialog. 
  • setMessage(): set the message to display in the dialog. 
  • setPositiveButton(): the first argument supplied is the text to show in the positive button, while the second argument is the listener called when the positive button is clicked. 
  • setNegativeButton(): the first argument supplied is the text to show in the negative button, while the second argument is the listener called when the negative button is clicked. 

Note that AlertDialog.Builder has a setView() to set your custom layout view to it. 

To show our dialog on the screen, we just invoke show().

Alert dialogAlert dialogAlert dialog

There is another setter method called setNeutralButton(). Calling this method will add another button on the far left side of the dialog. To call this method, we have to pass a String that will serve as the button text, and also a listener that is called when the button is tapped. 

1
new AlertDialog.Builder(this)
2
    // other setter methods 

3
    .setNeutralButton("Neutral", null)
4
    .show()
Alert dialog with neutral buttonAlert dialog with neutral buttonAlert dialog with neutral button

Note that touching outside the dialog will automatically dismiss it. To prevent that from happening, you will have to call the setCanceledOnTouchOutside() on the AlertDialog instance and pass false as an argument. 

1
AlertDialog dialog = new AlertDialog.Builder(this)
2
               // after calling setter methods

3
               .create();
4
dialog.setCanceledOnTouchOutside(false);
5
dialog.show();

To further prevent dismissing the dialog by pressing the BACK button, you then have to call setCancelable() on the AlertDialog instance and pass false to it as an argument. 

Styling an Alert Dialog

It's quite easy to style our dialog. We just create a custom style in the styles.xml resource. Observe that this style parent is Theme.AppCompat.Light.Dialog.Alert. In other words, this style inherits some style attributes from its parent. 

1
<style name="CustomDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
2
    <!--buttons color-->
3
    <item name="colorAccent">@android:color/holo_orange_dark</item>
4
    <!--title and message color-->
5
    <item name="android:textColorPrimary">@android:color/white</item>
6
    <!--dialog background-->
7
    <item name="android:windowBackground">@drawable/background_dialog</item>
8
</style>

We begin customising the dialog style by setting the values of the attributes to be applied on the dialog—for example, we can change the dialog button colour to be @android:color/holo_orange_dark and also set the dialog background to a custom drawable in our drawable resource folder (android:windowBackground set to @drawable/background_dialog).

Here is my background_dialog.xml resource file. 

1
<?xml version="1.0" encoding="utf-8"?>
2
<!-- From: support/v7/appcompat/res/drawable/abc_dialog_material_background_light.xml -->
3
<inset xmlns:android="https://schemas.android.com/apk/res/android"
4
       android:insetLeft="16dp"
5
       android:insetTop="16dp"
6
       android:insetRight="16dp"
7
       android:insetBottom="16dp">
8
9
    <shape android:shape="rectangle">
10
        <corners android:radius="10dp" />
11
        <solid android:color="@android:color/holo_green_dark" />
12
        <stroke android:width="5dp" android:color="@android:color/black" />
13
    </shape>
14
</inset>

Here we created a custom InsetDrawable which allows us to add insets on any side of the ShapeDrawable. We created a rectangle shape using the <shape> tag. We set the android:shape attribute of the <shape> tag to a rectangle (other possible values are line, oval, ring). We have a child tag <corners> that sets the radius of the rectangle corners. For a solid fill, we added the <solid> tag with an android:color attribute which indicates what color to use. Finally, we gave our drawable a border by using the <stroke> tag on the <shape>.

To apply this style to the dialog, we just pass the custom style to the second parameter in the AlertDialog.Builder constructor. 

1
AlertDialog dialog = new AlertDialog.Builder(this, R.style.CustomDialogTheme)
Alert dialog with custom styleAlert dialog with custom styleAlert dialog with custom style

2. Confirmation Dialogs

According to the material design documentation:

Confirmation dialogs require users to explicitly confirm their choice before an option is committed. For example, users can listen to multiple ringtones but only make a final selection upon touching “OK.”

The following different kinds of confirmation dialog are available:

  • multiple choice dialog
  • single choice dialog
  • date picker
  • time picker

Multiple Choice Dialog 

We utilize a multiple choice dialog when we want the user to select more than one item in a dialog. In a multiple choice dialog, a choice list is displayed for the user to choose from. 

1
String[] multiChoiceItems = getResources().getStringArray(R.array.dialog_multi_choice_array);
2
final boolean[] checkedItems = {false, false, false, false};
3
new AlertDialog.Builder(this)
4
        .setTitle("Select your favourite movies")
5
        .setMultiChoiceItems(multiChoiceItems, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
6
            @Override
7
            public void onClick(DialogInterface dialog, int index, boolean isChecked) {
8
                Log.d("MainActivity", "clicked item index is " + index);
9
            }
10
        })
11
        .setPositiveButton("Ok", null)
12
        .setNegativeButton("Cancel", null)
13
        .show();

To create a multiple choice dialog, we simply call the setMultiChoiceItems() setter method on the AlertDialog.Builder instance. Inside this method, we pass an Array of type String as the first parameter. Here's my array, located in the arrays resource file /values/arrays.xml

1
<?xml version="1.0" encoding="utf-8"?>
2
<resources>
3
    <string-array name="dialog_multi_choice_array">
4
        <item>The Dark Knight</item>
5
        <item>The Shawshank Redemption</item>
6
        <item>Saving Private Ryan</item>
7
        <item>The Silence of the Lambs</item>
8
    </string-array>
9
</resources>

The second parameter to the method setMultiChoiceItems() accepts an array which contains the items that are checked. The value of each element in the checkedItems array corresponds to each value in the multiChoiceItems array. We used our checkedItems array (the values of which are all false by default) to make all items unchecked by default. In other words, the first item "Dark Knight" is unchecked because the first element in the checkedItems array is false, and so on. If the first element in the checkedItems array was true instead, then "Dark Knight" would be checked.

Note that this array checkedItems is updated when we select or click on any item displayed—for example, if the user should select "The Shawshank Redemption", calling checkedItems[1] would return true

The last parameter accepts an instance of OnMultiChoiceClickListener. Here we simply create an anonymous class and override onClick(). We get an instance of the shown dialog in the first parameter. In the second parameter, we get the index of the item that was selected. Finally, in the last parameter, we find out if the selected item was checked or not. 

Multichoice dialog Multichoice dialog Multichoice dialog

Single Choice Dialog 

In a single choice dialog, unlike the multiple choice dialog, only one item can be selected. 

1
String[] singleChoiceItems = getResources().getStringArray(R.array.dialog_single_choice_array);
2
int itemSelected = 0;
3
new AlertDialog.Builder(this)
4
        .setTitle("Select your gender")
5
        .setSingleChoiceItems(singleChoiceItems, itemSelected, new DialogInterface.OnClickListener() {
6
            @Override
7
            public void onClick(DialogInterface dialogInterface, int selectedIndex) {
8
9
            }
10
        })
11
        .setPositiveButton("Ok", null)
12
        .setNegativeButton("Cancel", null)
13
        .show();

To create a single choice dialog, we simply invoke the setSingleChoiceItems() setter on the AlertDialog.Builder instance. Inside this method, we also pass an Array of type String as the first parameter. Here's the array we passed, which is located in the arrays resource file: /values/arrays.xml

1
<?xml version="1.0" encoding="utf-8"?>
2
<resources>
3
   <! -- ... -->
4
   <string-array name="dialog_single_choice_array">
5
        <item>Male</item>
6
        <item>Female</item>
7
        <item>Others</item>
8
    </string-array>
9
</resources>

The second parameter of the setSingleChoiceItems() is used to determine which item is checked. The last parameter in onClick() gives us the index of the item that was selected—for example, selecting the Female item, the value of selectedIndex will be 1

Single choice dialogSingle choice dialogSingle choice dialog

Date Picker Dialog

This is a dialog picker that is used to select a single date.

To start, we'll create a Calendar field instance in the MainActivity and initialize it. 

1
public class MainActivity extends AppCompatActivity {
2
    Calendar mCalendar = Calendar.getInstance();
3
// ...

Here we called Calendar.getInstance() to get the current time (in the default time zone) and set it to the mCalendar field. 

1
DatePickerDialog datePickerDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
2
    @Override
3
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
4
        mCalendar.set(Calendar.YEAR, year);
5
        mCalendar.set(Calendar.MONTH, monthOfYear);
6
        mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
7
        String date = DateFormat.getDateInstance(DateFormat.MEDIUM).format(calendar.getTime());
8
        Log.d("MainActivity", "Selected date is " + date);
9
    }
10
}, mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH));
11
datePickerDialog.show();

To show a date picker dialog, we create an instance of the DatePickerDialog. Here is the explanation of the parameter definitions when creating an instance of this type. 

  • The first parameter accepts a parent context—for example, in an Activity, you use this, while in a Fragment, you call getActivity().  
  • The second parameter accepts a listener of type OnDateSetListener. This listener onDateSet() is called when the user sets the date. Inside this method, we get the selected year, the selected month of the year, and also the selected day of the month. 
  • The third parameter is the initially selected year. 
  • The fourth parameter is the initially selected month (0-11). 
  • The last parameter is the initially selected day of the month (1-31). 

Finally, we call the show() method of the DatePickerDialog instance to display it on the current screen. 

Date picker dialogDate picker dialogDate picker dialog

Setting a Custom Theme

It's quite easy to customize the theme of the date picker dialog (similar to what we did to the alert dialog). 

Briefly, you create a custom drawable, create a custom style or theme, and then apply that theme when creating a DatePickerDialog instance in the second parameter.  

1
DatePickerDialog datePickerDialog = 
2
  new DatePickerDialog(this, R.style.MyCustomDialogTheme, listener, 2017, 26, 11);

Time Picker Dialog

The time picker dialog allows the user to pick a time, and adjusts to the user’s preferred time setting, i.e. the 12-hour or 24-hour format.

As you can see in the code below, creating a TimePickerDialog is quite similar to creating a DatePickerDialog. When creating an instance of the TimePickerDialog, we pass in the following parameters:

  • The first parameter accepts a parent context. 
  • The second parameter accepts an OnTimeSetListener instance that serves as a listener.
  • The third parameter is the initial hour of the day. 
  • The fourth parameter is the initial minute.
  • The last parameter is to set whether we want the view in 24-hour or AM/PM format. 
1
TimePickerDialog timePickerDialog = 
2
new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
3
    @Override
4
    public void onTimeSet(TimePicker timePicker, int hourOfDay, int minute) {
5
        mCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
6
        mCalendar.set(Calendar.MINUTE, minute);
7
        String time = DateFormat.getTimeInstance(DateFormat.SHORT).format(calendar.getTime());
8
        Log.d("MainActivity", "Selected time is " + time);
9
    }
10
}, mCalendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), true);
11
timePickerDialog.show();

The onTimeSet() method is called every time the user has selected the time. Inside this method, we get an instance of the TimePicker, the selected hour of the day chosen, and also the selected minute. 

To display this dialog, we still call the show() method.

Time picker dialogTime picker dialogTime picker dialog

The time picker can be styled in a similar way to the date picker dialog. 

3. Bottom Sheet Dialog

According to the official Google material design documentation:

Bottom sheets slide up from the bottom of the screen to reveal more content.

To begin using the bottom sheet dialog, you have to import the design support artifact—so visit your app module's build.gradle file to import it. 

1
dependencies {
2
    implementation 'com.android.support:appcompat-v7:26.1.0'
3
    implementation 'com.android.support:design:26.1.0'
4
}

Make sure that the activity or fragment for the bottom sheet dialog will pop up—its parent layout is the CoordinatorLayout

1
<android.support.design.widget.CoordinatorLayout
2
        xmlns:android="http://schemas.android.com/apk/res/android"
3
        xmlns:tools="http://schemas.android.com/tools"
4
        xmlns:app="http://schemas.android.com/apk/res-auto"
5
        android:layout_width="match_parent"
6
        android:layout_height="match_parent"
7
    <!-- ... -->
8
9
    <!--bottom sheet container-->
10
    <FrameLayout
11
            android:id="@+id/framelayout_bottom_sheet"
12
            android:layout_width="match_parent"
13
            android:layout_height="wrap_content"
14
            app:layout_behavior="@string/bottom_sheet_behavior" />
15
</android.support.design.widget.CoordinatorLayout>

Here we also have a FrameLayout that would serve as a container for our bottom sheet. Observe that one of this FrameLayout's attributes is app:layout_behavior, whose value is a special string resource that maps to android.support.design.widget.BottomSheetBehavior. This will enable our FrameLayout to appear as a bottom sheet. Note that if you don't include this attribute, your app will crash. 

1
public class MainActivity extends AppCompatActivity {// ... 

2
   
3
    // ... 

4
    private BottomSheetDialog mBottomSheetDialog;
5
    
6
    @Override
7
    protected void onCreate(Bundle savedInstanceState) {
8
        super.onCreate(savedInstanceState);
9
        setContentView(R.layout.activity_main);
10
        // ... 

11
        View bottomSheet = findViewById(R.id.framelayout_bottom_sheet);
12
    }
13
}

Here we declared an instance of BottomSheetDialog as a field to our MainActivity.java and initialized it in the onCreate() method of our activity. 

1
final View bottomSheetLayout = getLayoutInflater().inflate(R.layout.bottom_sheet_dialog, null);
2
(bottomSheetLayout.findViewById(R.id.button_close)).setOnClickListener(new View.OnClickListener() {
3
    @Override
4
    public void onClick(View view) {
5
        mBottomSheetDialog.dismiss();
6
    }
7
});
8
(bottomSheetLayout.findViewById(R.id.button_ok)).setOnClickListener(new View.OnClickListener() {
9
    @Override
10
    public void onClick(View v) {
11
        Toast.makeText(getApplicationContext(), "Ok button clicked", Toast.LENGTH_SHORT).show();
12
    }
13
});
14
15
mBottomSheetDialog = new BottomSheetDialog(this);
16
mBottomSheetDialog.setContentView(bottomSheetLayout);
17
mBottomSheetDialog.show();

In the preceding code, we inflated our bottom sheet layout R.layout.bottom_sheet_dialog. We set listeners for the Cancel and Ok buttons in the bottom_sheet_dialog.xml. When the Cancel button is clicked, we simply dismiss the dialog. 

We then initialized our mBottomSheetDialog field and set the view using setContentView(). Finally, we call the show() method to display it on the screen. 

Here is my bottom_sheet_dialog.xml:

1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
              android:layout_width="match_parent"
4
              android:layout_height="wrap_content"
5
              android:layout_gravity="bottom"
6
              android:orientation="vertical"
7
              android:padding="15dp">
8
9
    <TextView
10
            android:id="@+id/tv_title"
11
            android:layout_width="wrap_content"
12
            android:layout_height="match_parent"
13
            android:layout_marginBottom="10dp"
14
            android:layout_marginTop="10dp"
15
            android:text="Title"
16
            android:textAppearance="@style/TextAppearance.AppCompat.Title" />
17
18
    <TextView
19
            android:id="@+id/tv_detail"
20
            android:layout_width="wrap_content"
21
            android:layout_height="match_parent"
22
            android:layout_marginTop="5dp"
23
            android:text="@string/lorem_ipsum"
24
            android:textAppearance="@style/TextAppearance.AppCompat.Subhead"/>
25
26
    <LinearLayout
27
            android:layout_width="match_parent"
28
            android:layout_height="wrap_content"
29
            android:layout_marginTop="15dp"
30
            android:gravity="right"
31
            android:orientation="horizontal">
32
33
        <Button
34
                android:id="@+id/button_close"
35
                style="@style/Base.Widget.AppCompat.Button.Borderless.Colored"
36
                android:layout_width="wrap_content"
37
                android:layout_height="wrap_content"
38
                android:text="CLOSE" />
39
40
        <Button
41
                android:id="@+id/button_ok"
42
                style="@style/Base.Widget.AppCompat.Button.Borderless.Colored"
43
                android:layout_width="wrap_content"
44
                android:layout_height="wrap_content"
45
                android:text="OK" />
46
    </LinearLayout>
47
</LinearLayout>
Bottom sheet dialogBottom sheet dialogBottom sheet dialog

Make sure you check out How to Use Bottom Sheets With the Design Support Library by Paul Trebilcox-Ruiz here on Envato Tuts+ to learn more about botttom sheets.

4. Full-Screen Dialog

According to the official Google material design documentation:

Full-screen dialogs group a series of tasks (such as creating a calendar entry) before they may be committed or discarded. No selections are saved until “Save” is touched. Touching the “X” discards all changes and exits the dialog.

Let's now see how to create a full-screen dialog. First, make sure you include the Android support v4 artifact in your app's module build.gradle. This is required to support Android 4.0 (API level 14) and above. 

1
implementation 'com.android.support:support-v4:26.1.0'

Next, we will create a FullscreenDialogFragment that extends the DialogFragment super class. 

1
public class FullscreenDialogFragment extends DialogFragment {
2
3
    @Override
4
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
5
        View rootView = inflater.inflate(R.layout.full_screen_dialog, container, false);
6
       (rootView.findViewById(R.id.button_close)).setOnClickListener(new View.OnClickListener() {
7
            @Override
8
            public void onClick(View v) {
9
                dismiss();
10
            }
11
        });
12
        return rootView;
13
    }
14
15
    @NonNull
16
    @Override
17
    public Dialog onCreateDialog(Bundle savedInstanceState) {
18
        Dialog dialog = super.onCreateDialog(savedInstanceState);
19
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
20
        return dialog;
21
    }
22
}

Here we override the onCreateView() (just as we would do with an ordinary Fragment). Inside this method, we simply inflate and return the layout (R.layout.full_screen_dialog) that will serve as the custom view for the dialog. We set an OnClickListener on the ImageButton (R.id.button_close) which will dismiss the dialog when clicked. 

We also override onCreateDialog() and return a Dialog. Inside this method, you can also return an AlertDialog created using an AlertDialog.Builder

Our R.layout.full_screen_dialog consists of an ImageButton, a Button, and some TextView labels:

1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
              xmlns:app="http://schemas.android.com/apk/res-auto"
4
              android:layout_width="match_parent"
5
              android:layout_height="match_parent"
6
              android:background="@android:color/white"
7
              android:fitsSystemWindows="true"
8
              android:orientation="vertical">
9
10
    <android.support.design.widget.AppBarLayout
11
            android:layout_width="match_parent"
12
            android:layout_height="?attr/actionBarSize">
13
14
        <LinearLayout
15
                android:layout_width="match_parent"
16
                android:layout_height="match_parent"
17
                android:orientation="horizontal">
18
19
            <ImageButton
20
                    android:id="@+id/button_close"
21
                    android:layout_width="?attr/actionBarSize"
22
                    android:layout_height="?attr/actionBarSize"
23
                    android:background="?attr/selectableItemBackgroundBorderless"
24
                    android:tint="@android:color/white"
25
                    app:srcCompat="@drawable/ic_close" />
26
27
            <TextView
28
                    android:layout_width="0dp"
29
                    android:layout_height="match_parent"
30
                    android:layout_weight="1"
31
                    android:gravity="center_vertical"
32
                    android:text="Dialog title"
33
                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Title"
34
                    android:textColor="@android:color/white" />
35
36
            <Button
37
                    android:id="@+id/button_action"
38
                    style="@style/Widget.AppCompat.Button.Borderless"
39
                    android:layout_width="wrap_content"
40
                    android:layout_height="match_parent"
41
                    android:gravity="center"
42
                    android:paddingLeft="2dp"
43
                    android:paddingRight="2dp"
44
                    android:text="Action"
45
                    android:textColor="@android:color/white" />
46
47
        </LinearLayout>
48
49
    </android.support.design.widget.AppBarLayout>
50
51
    <android.support.v4.widget.NestedScrollView
52
            android:id="@+id/nested_scroll_view"
53
            android:layout_width="match_parent"
54
            android:layout_height="match_parent"
55
            android:scrollbars="none"
56
            android:scrollingCache="true">
57
58
        <TextView
59
                android:layout_width="wrap_content"
60
                android:layout_height="wrap_content"
61
                android:layout_gravity="center_horizontal|center_vertical"
62
                android:text="Full Screen Dialog"/>
63
64
    </android.support.v4.widget.NestedScrollView>
65
66
</LinearLayout>

In the ImageButton widget, you will see an attribute app:srcCompat which references a custom VectorDrawable (@drawable/ic_close). This custom VectorDrawable creates the X button, which closes the full-screen dialog when tapped. 

1
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2
        android:width="24dp"
3
        android:height="24dp"
4
        android:viewportWidth="24.0"
5
        android:viewportHeight="24.0">
6
    <path
7
        android:fillColor="#FFFFFFFF"
8
        android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
9
</vector>

In order to use this app:srcCompat attribute, make sure you include it in your build.gradle file. Next, configure your app to use vector support libraries and add the vectorDrawables element to your build.gradle file in the app module.

1
android {
2
    defaultConfig {
3
       vectorDrawables.useSupportLibrary = true
4
    }

We did this so that we can support all Android platform versions back to Android 2.1 (API level 7+). 

Finally, to show the FullscreenDialogFragment, we simply use the FragmentTransaction to add our fragment to the UI. 

1
FragmentManager fragmentManager = getSupportFragmentManager();
2
FullscreenDialogFragment newFragment = new FullscreenDialogFragment();
3
FragmentTransaction transaction = fragmentManager.beginTransaction();
4
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
5
transaction.add(android.R.id.content, newFragment).addToBackStack(null).commit();
Full screen dialog Full screen dialog Full screen dialog

5. Surviving Device Orientation

Note that all the dialogs discussed here, except the full-screen dialog, will be dismissed automatically when the user changes the screen orientation of the Android device—from portrait to landscape (or vice versa). This is because the Android system has destroyed and recreated the Activity so as to fit the new orientation. 

For us to sustain the dialog across screen orientation changes, we'll have to create a Fragment that extends the DialogFragment super class (just as we did for the full-screen dialog example). 

Let's see a simple example for an alert dialog. 

1
public class AlertDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
2
3
    @Override
4
    public Dialog onCreateDialog(Bundle savedInstanceState) {
5
6
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
7
        return (builder.setTitle("Activate superpowers?").setMessage("By activating superpowers, you'll have more powers to save the world.")
8
                       .setPositiveButton("Activate", this)
9
                       .setNegativeButton("Cancel", this)
10
                       .create());
11
    }
12
13
    @Override
14
    public void onCancel(DialogInterface dialog) {
15
        super.onCancel(dialog);
16
    }
17
18
    @Override
19
    public void onDismiss(DialogInterface dialog) {
20
        super.onDismiss(dialog);
21
    }
22
23
    @Override
24
    public void onClick(DialogInterface dialog, int which) {
25
        Toast.makeText(getActivity(), "which is " + which, Toast.LENGTH_LONG).show();
26
    }
27
}

Here, we created a class that extends the DialogFragment and also implements the DialogInterface.OnClickListener. Because we implemented this listener, we have to override the onClick() method. Note that if we tap the positive or negative button, this onClick() method will be invoked. 

Inside our onCreateDialog(), we create and return an instance of AlertDialog

We've also overridden:

  • onCancel(): this is called if the user presses the BACK button to exit the dialog. 
  • onDismiss(): this is called whenever the dialog is forced out for any reason (BACK or a button click). 

To show this dialog, we simply call the show() method on an instance of our AlertDialogFragment

1
new AlertDialogFragment().show(getSupportFragmentManager(), "alertdialog_sample");

The first parameter is an instance of the FragmentManager. The second parameter is a tag that can be used to retrieve this fragment again later from the FragmentManager via findFragmentByTag().

Alert dialog on rotationAlert dialog on rotationAlert dialog on rotation

Now, if you change the device orientation from portrait to landscape (or vice versa), the alert dialog won't be dismissed. 

You can follow similar steps for the other dialog types to maintain the dialog during device rotation. You simply create a Fragment that extends the DialogFragment super class, and you create and return the particular dialog in onCreateDialog()

Progress Dialog (deprecated)

Some of you may have heard about ProgressDialog. This simply shows a dialog with a progress indicator on it. I didn't include it here, because ProgressDialog has been deprecated in API level 26—because it can lead to a bad user experience for your users. According to the official documentation:

ProgressDialog is a modal dialog, which prevents the user from interacting with the app. Instead of using this class, you should use a progress indicator like ProgressBar, which can be embedded in your app's UI. Alternatively, you can use a notification to inform the user of the task's progress.

Conclusion

In this tutorial, you learned the different ways of showing material design dialogs in an Android app. We covered the following material design dialog types:

  • alerts
  • single and multiple choice dialogs
  • time and date pickers
  • bottom sheet dialog
  • full-screen dialog

You also learned how to create a custom style for a dialog and make your dialog survive orientation configuration changes between landscape and portrait using DialogFragment

It's highly recommended you check out the official material design guidelines for dialogs to learn how to properly design and use dialogs in Android.   

To learn more about coding for Android, check out some of our other courses and tutorials here on Envato Tuts+!

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.