-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Using DialogFragment
DialogFragment is a specialized Fragment used when you want to display an overlay modal window within an activity that floats on top of the rest of the content.
This is typically used for displaying an alert dialog, a confirm dialog, or prompting the user for information within an overlay without having to switch to another Activity.
DialogFragment is now the canonical way to display overlays; using Dialog directly is considered bad practice.
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.
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
:
<!-- fragment_edit_name.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/edit_name"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:orientation="vertical" >
<TextView
android:id="@+id/lbl_your_name" android:text="Your name"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
<EditText
android:id="@+id/txt_your_name"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:inputType="text"
android:imeOptions="actionDone" />
</LinearLayout>
and defining the fragment itself extending from the support version of dialog fragment:
import android.support.v4.app.DialogFragment;
// ...
public class EditNameDialog extends DialogFragment {
private EditText mEditText;
public EditNameDialog() {
// Empty constructor required for DialogFragment
}
public static EditNameDialog newInstance(String title) {
EditNameDialog frag = new EditNameDialog();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container);
mEditText = (EditText) view.findViewById(R.id.txt_your_name);
String title = getArguments().getString("title", "Enter Name");
getDialog().setTitle(title);
// Show soft keyboard automatically
mEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
return view;
}
}
and showing the dialog in an Activity (extending FragmentActivity or AppCompatActivity):
// Note: `FragmentActivity` works here as well
public class FragmentDialogDemo extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showEditDialog();
}
private void showEditDialog() {
FragmentManager fm = getSupportFragmentManager();
EditNameDialog editNameDialog = EditNameDialog.newInstance("Some Title");
editNameDialog.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.
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.
class MyAlertDialogFragment extends DialogFragment {
public MyAlertDialogFragment() {
// Empty constructor required for DialogFragment
}
public static MyAlertDialogFragment newInstance(String title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments().getString("title");
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setMessage("Are you sure?");
alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// on success
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
return alertDialogBuilder.create();
}
}
and to display the alert dialog in an activity (extending FragmentActivity
or AppCompatActivity
):
// Note: `AppCompatActivity` works here as well
public class FragmentDialogDemo extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
showAlertDialog();
}
private void showAlertDialog() {
FragmentManager fm = getSupportFragmentManager();
MyAlertDialogFragment alertDialog = MyAlertDialogFragment.newInstance("Some title");
alertDialog.show(fm, "fragment_alert");
}
}
To pass data from a dialog to an Activity, use the same approach you would use for any fragment. This is called the "fragment interface pattern". This is demonstrated for the onCreateView
approach
but works similarly for the AlertDialog (just use the listeners defined for the buttons):
public class EditNameDialog extends DialogFragment implements OnEditorActionListener {
private EditText mEditText;
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
// ...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// ...
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)
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (EditorInfo.IME_ACTION_DONE == actionId) {
// Return input text to activity
EditNameDialogListener listener = (EditNameDialogListener) getActivity();
listener.onFinishEditDialog(mEditText.getText().toString());
dismiss();
return true;
}
return false;
}
}
and have the activity define the action to take when the dialog has the information:
public class FragmentDialogDemo extends FragmentActivity implements EditNameDialogListener {
// ...
@Override
public void onFinishEditDialog(String inputText) {
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.
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
:
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- Apply default style for dialogs -->
<item name="dialogTheme">@style/AppDialogTheme</item>
<!-- Apply default style for alert dialogs -->
<item name="alertDialogTheme">@style/AppAlertTheme</item>
</style>
<!-- Define your custom dialog theme here extending from base -->
<style name="AppDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">@color/dark_blue</item>
<item name="colorPrimaryDark">#000</item>
<item name="colorAccent">@color/dark_blue</item>
<item name="colorControlNormal">@color/dark_blue</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:background">#4CAF50</item>
<item name="android:textColorHighlight">@color/light_blue</item>
</style>
<!-- Define your custom alert theme here extending from base -->
<style name="AppAlertTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorPrimary">@color/dark_blue</item>
<item name="colorAccent">@color/dark_blue</item>
<item name="colorPrimaryDark">#000</item>
<item name="colorControlNormal">@color/dark_blue</item>
<item name="android:textColorHighlight">@color/light_blue</item>
</style>
Note that third party libraries can be used to simplify and improve styling as well.
In certain situations, you may want to 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:
<!-- fragment_edit_name.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/edit_name"
android:layout_width="match_parent" android:layout_height="match_parent" >
<!-- ...subviews here... -->
</LinearLayout>
In the DialogFragment
java source we can set the width and height onResume
with:
public void onResume() {
int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);
getDialog().getWindow().setLayout(width, height);
}
See this stackoverflow post for more information.
When using the onCreateDialog
method there are many built-in Dialog types to take advantage of:
- AlertDialog - Base dialog that can display a message, an icon and 1-3 buttons with customized text.
- ProgressDialog - Dialog showing a progress indicator and an optional text message
- TimePickerDialog - Dialog that allows a user to select a time.
- DatePickerDialog - Dialog that allows a user to select a date.
- Other dialogs not worth discussing here.
When running a long running background task, one easy way to notify users the app is loading is to display a ProgressDialog.
A ProgressDialog
can be created anytime with the following:
ProgressDialog pd = new ProgressDialog(context);
pd.setTitle("Loading...");
pd.setMessage("Please wait.");
pd.setCancelable(false);
The dialog can be displayed with:
pd.show();
and hidden anytime with:
pd.dismiss();
ProgressDialog
can be safely paired with an AsyncTask. Refer to this ProgressDialog tutorial for a code sample. The dialog progress animation can be customized by supplying your own animation drawable using this tutorial.
- 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 theshow()
method.
- CodePath android-view-helpers for an easier way to create simple alert and progress modals.
- http://android-developers.blogspot.com/2012/05/using-dialogfragments.html
- http://codebaum.wordpress.com/2013/04/10/dialog-fragments/
- http://developer.android.com/reference/android/app/DialogFragment.html
- http://www.coderzheaven.com/2013/02/14/dialogfragments-android-simple-example/
- http://stackoverflow.com/questions/12912181/simplest-yes-no-dialog-fragment
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.