Usage

The minimum that must be implemented when creating a DialogFragment is either the onCreateView method or the onCreateDialog method. Use onCreateView when the entire view of the dialog is going to be defined via custom XML. Use onCreateDialog when you just need to construct and configure a standard Dialog class (such as AlertDialog) to display.

Note: The entire guide below requires every fragment related class imported to use the android.support.v4.app namespace and not the android.app namespace. If any imported class (FragmentManager, DialogFragment, etc) uses the android.app namespace, compile-time errors will occur.

Custom View

Let's start by providing the code for creating a completely custom dialog based on an XML view. First, an example fragment XML file in res/layout/fragment_edit_name.xml:

and defining the fragment itself extending from the support version of dialog fragment:

importandroid.support.v4.app.DialogFragment;// ...
publicclassEditNameDialogFragmentextendsDialogFragment{privateEditTextmEditText;publicEditNameDialogFragment(){// Empty constructor is required for DialogFragment
// Make sure not to add arguments to the constructor
// Use `newInstance` instead as shown below
}publicstaticEditNameDialogFragmentnewInstance(Stringtitle){EditNameDialogFragmentfrag=newEditNameDialogFragment();Bundleargs=newBundle();args.putString("title",title);frag.setArguments(args);returnfrag;}@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){returninflater.inflate(R.layout.fragment_edit_name,container);}@OverridepublicvoidonViewCreated(Viewview,@NullableBundlesavedInstanceState){super.onViewCreated(view,savedInstanceState);// Get field from view
mEditText=(EditText)view.findViewById(R.id.txt_your_name);// Fetch arguments from bundle and set title
Stringtitle=getArguments().getString("title","Enter Name");getDialog().setTitle(title);// Show soft keyboard automatically and request focus to field
mEditText.requestFocus();getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);}}

and showing the dialog in an Activity extending AppCompatActivity:

// Note: `FragmentActivity` works here as well
publicclassDialogDemoActivityextendsAppCompatActivity{@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);showEditDialog();}privatevoidshowEditDialog(){FragmentManagerfm=getSupportFragmentManager();EditNameDialogFragmenteditNameDialogFragment=EditNameDialogFragment.newInstance("Some Title");editNameDialogFragment.show(fm,"fragment_edit_name");}}

For this to work properly make sure that all the fragment related items (FragmentDialog) are from the android.support.v4.app namespace.

Build Dialog

Second, let's take a look at how to build a dialog simply by customizing the available
Dialog objects that we can construct. For more details about the different types of dialogs, check out the "Things to Note" section below.

Passing Data to Activity

To pass data from a dialog to an Activity, use the same approach you would use for any fragment which is creating a custom listener. In short, you will need to do the following:

Define an interface with methods that can be invoked to pass data result to the activity

Setup a view event which invokes the custom listener passing data through the method

Implement the interface in the Activity defining behavior for when the event is triggered

This example below demonstrates how to pass a data result back to the activity when the "Done" button is pressed on the keyboard but this works similarly for other cases or for the AlertDialog (just use the listeners defined for each of the buttons):

publicclassEditNameDialogFragmentextendsDialogFragmentimplementsOnEditorActionListener{privateEditTextmEditText;// 1. Defines the listener interface with a method passing back data result.
publicinterfaceEditNameDialogListener{voidonFinishEditDialog(StringinputText);}// ...
@OverridepublicvoidonViewCreated(Viewview,@NullableBundlesavedInstanceState){// ...
// 2. Setup a callback when the "Done" button is pressed on keyboard
mEditText.setOnEditorActionListener(this);}// Fires whenever the textfield has an action performed
// In this case, when the "Done" button is pressed
// REQUIRES a 'soft keyboard' (virtual keyboard)
@OverridepublicbooleanonEditorAction(TextViewv,intactionId,KeyEventevent){if(EditorInfo.IME_ACTION_DONE==actionId){// Return input text back to activity through the implemented listener
EditNameDialogListenerlistener=(EditNameDialogListener)getActivity();listener.onFinishEditDialog(mEditText.getText().toString());// Close the dialog and return back to the parent activity
dismiss();returntrue;}returnfalse;}}

and have the activity define the action to take when the dialog has the information:

publicclassDialogDemoActivityextendsAppCompatActivityimplementsEditNameDialogListener{// ...
// 3. This method is invoked in the activity when the listener is triggered
// Access the data result passed to the activity here
@OverridepublicvoidonFinishEditDialog(StringinputText){Toast.makeText(this,"Hi, "+inputText,Toast.LENGTH_SHORT).show();}}

Note:setOnEditorActionListener used above to dismiss requires the use of the soft keyboard in the emulator which can be enabled through AVD or by testing on a device. If you don't want to enable soft keyboard, you may want to dismiss on a button click or on a keypress instead.

Passing Data to Parent Fragment

In certain situations, the a dialog fragment may be invoked within the context of another fragment. For example, a screen has tabs with a form contained in a fragment. The form has an input for selecting dates using a date picker in a dialog. In this case, we may want to pass the date back not to the activity but instead to the parent fragment. This data can be passed back directly to the parent fragment:

importandroid.support.v4.app.DialogFragment;publicclassEditNameDialogFragmentextendsDialogFragment{// Defines the listener interface
publicinterfaceEditNameDialogListener{voidonFinishEditDialog(StringinputText);}// Call this method to send the data back to the parent fragment
publicvoidsendBackResult(){// Notice the use of `getTargetFragment` which will be set when the dialog is displayed
EditNameDialogListenerlistener=(EditNameDialogListener)getTargetFragment();listener.onFinishEditDialog(mEditText.getText().toString());dismiss();}}

And then the dialog must be displayed within a parent fragment passing the target via setTargetFragment with:

importandroid.support.v4.app.Fragment;publicclassMyParentFragmentextendsFragmentimplementsEditNameDialogListener{// Call this method to launch the edit dialog
privatevoidshowEditDialog(){FragmentManagerfm=getFragmentManager();EditNameDialogFragmenteditNameDialogFragment=EditNameDialog.newInstance("Some Title");// SETS the target fragment for use later when sending results
editNameDialogFragment.setTargetFragment(MyParentFragment.this,300);editNameDialogFragment.show(fm,"fragment_edit_name");}// This is called when the dialog is completed and the results have been passed
@OverridepublicvoidonFinishEditDialog(StringinputText){Toast.makeText(this,"Hi, "+inputText,Toast.LENGTH_SHORT).show();}}

Troubleshooting

If you are having any issues, be sure to use the checklist below:

In parent fragment, before calling dialogFragment.show(), are you calling setTargetFragment and passing in the correct fragment as the target?

In the dialog fragment, before calling dismiss(), are you calling listener.someCallbackMethod() on a listener casted from the getTargetFragment() passed in above?

Have you correctly implemented the interface and callback method fired i.e listener.someCallbackMethod() inside of the parent fragment?

Try breakpointing each of those lines to make sure the target fragment is set property and the callback method is being executed.

With that, the two fragments are able to pass data back and forth.

Styling Dialogs

Styling Custom Dialog

Styling a DialogFragment with a custom layout works just the same as styling any views. Styling a dialog or AlertDialog requires changing several key properties in styles.xml such as the dialogTheme and alertDialogTheme as shown in this app here and shown below in res/values/styles.xml:

Dialog Styling Workaround

Note: There is currently a bug in the support library that causes styles not to show up properly. Changing the DialogFragment in the onCreateView to use the activity's inflater seems to resolve the issue:

Removing the TitleBar from the Dialog

The TitleBar can be easily removed from your DialogFragment by overriding the onCreateDialog method:

@OverridepublicDialogonCreateDialog(BundlesavedInstanceState){Dialogdialog=super.onCreateDialog(savedInstanceState);// request a window without the title
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);returndialog;}

Styling with Third-Party Libraries

In order to use the "material-dialogs" library, you will need to add in maven repository to your build.gradle file. Your gradle file should look something like this.

Sizing Dialogs

Runtime Dimensions

In certain situations, you may want to explicitly set the height and width of the DialogFragment at runtime during creation. This can be done easily with getDialog().getWindow() as follows. In the XML simply set the root layout to wrap_content with:

See this stackoverflow post for more information. Using this approach we could set the dialog's width as a percentage of the screen within the DialogFragment with:

publicvoidonResume(){// Store access variables for window and blank point
Windowwindow=getDialog().getWindow();Pointsize=newPoint();// Store dimensions of the screen in `size`
Displaydisplay=window.getWindowManager().getDefaultDisplay();display.getSize(size);// Set the width of the dialog proportional to 75% of the screen width
window.setLayout((int)(size.x*0.75),WindowManager.LayoutParams.WRAP_CONTENT);window.setGravity(Gravity.CENTER);// Call super onResume after sizing
super.onResume();}

Sizing Adjustments for Soft Keyboard

When displaying a dialog that is accepting text input, there can often be limited space on screen because the soft keyboard on screen eats up a lot of room. To account for this, you may want to modify the android:windowSoftInputMode property for the activity within the AndroidManifest.xml file:

<!-- Configures the UI to be resized to make room for the keyboard --><activityandroid:name="com.example.myactivity"android:windowSoftInputMode="adjustResize"/>

See the full details in the working with the soft keyboard guide. Alternatively, we could perform the resize directly at runtime within the onCreateView method of the fragment:

Check out the CodePath android-view-helpers library for an easier way to create simple alert and progress modals.

Displaying Date or Time Picker Dialogs

The native date and time pickers for Android are another example of specialized dialog fragments. Please note that the date/time pickers that comes with the Android SDK differ depending on the Android device version. See this section for more information.

If you wish for the containing activity to receive the date or time selected by the dialog, you should ensure that the Activity implements the respective interface. If we want the date picker to be shown from within another dialog fragment, refer to setting a target fragment. For instance, for a date picker fragment, you will want to ensure that the activity implements the OnDateSetListener interface:

importjava.util.Calendar;// do not import java.icu.utils.Calendar
publicclassDatePickerFragmentextendsDialogFragment{@OverridepublicDialogonCreateDialog(BundlesavedInstanceState){// Use the current time as the default values for the picker
finalCalendarc=Calendar.getInstance();intyear=c.get(Calendar.YEAR);intmonth=c.get(Calendar.MONTH);intday=c.get(Calendar.DAY_OF_MONTH);// Activity needs to implement this interface
DatePickerDialog.OnDateSetListenerlistener=(DatePickerDialog.OnDateSetListener)getActivity();// Create a new instance of TimePickerDialog and return it
returnnewDatePickerDialog(getActivity(),listener,year,month,day);}

The Activity, which also is responsible for instantiating this dialog fragment, simply needs to implement the onDateSet method of this interface.

publicclassMyActivityextendsAppCompatActivityimplementsDatePickerDialog.OnDateSetListener{// attach to an onclick handler to show the date picker
publicvoidshowDatePickerDialog(Viewv){DatePickerFragmentnewFragment=newDatePickerFragment();newFragment.show(getSupportFragmentManager(),"datePicker");}// handle the date selected
@OverridepublicvoidonDateSet(DatePickerview,intyear,intmonthOfYear,intdayOfMonth){// store the values selected into a Calendar instance
finalCalendarc=Calendar.getInstance();c.set(Calendar.YEAR,year);c.set(Calendar.MONTH,monthOfYear);c.set(Calendar.DAY_OF_MONTH,dayOfMonth);}

A similar approach can be done with the time picker too:

publicclassTimePickerFragmentextendsDialogFragment{@OverridepublicDialogonCreateDialog(BundlesavedInstanceState){// Use the current time as the default values for the picker
finalCalendarc=Calendar.getInstance();inthour=c.get(Calendar.HOUR_OF_DAY);intminute=c.get(Calendar.MINUTE);// Activity has to implement this interface
TimePickerDialog.OnTimeSetListenerlistener=(TimePickerDialog.OnTimeSetListener)getActivity();// Create a new instance of TimePickerDialog and return it
returnnewTimePickerDialog(getActivity(),listener,hour,minute,DateFormat.is24HourFormat(getActivity()));}publicvoidonTimeSet(TimePickerview,inthourOfDay,intminute){// Do something with the time chosen by the user
}}

Modal Bottom Sheets

With the support design library, it also fairly easy to convert your dialog to use modal bottom sheets. Instead of DialogFragment, you can extend from BottomSheetDialogFragment:

Things To Note

Notice that we are using the support library version of fragments for better compatibility in our code samples. The non-support version works identically.

Dialogs are just classes that extend DialogFragment and define the view to display in the floating content area.

DialogFragment classes must define an empty constructor as shown in the code samples, otherwise the Android system will raise an exception when it attempts to instantiate the fragment.

After loading the initial view, the activity immediately shows the dialog using the show() method which allows the fragment manager to keep track of the state and gives us certain things for free such as the back button dismissing the fragment.

In the code snippets above, notice the use of requestFocus and input modes to control the appearance of the soft keyboard when the dialog appears.

We can dismiss a dialog one of two ways. Here we are calling dismiss() within the Dialog class itself. It could also be called from the Activity like the show() method. In API 13, removeDialog(int id) and dismissDialog(int id) were deprecated. dismiss() directly on the dialog is now the recommended approach as outlined here.