diff options
author | Scott Main <smain@google.com> | 2012-10-03 16:17:13 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-10-03 16:17:13 -0700 |
commit | d4c18b01cc152f97ea30146d0ad795c05b59e178 (patch) | |
tree | b0fb411d2f96fffaa56ff7c5d3433edff02f3552 | |
parent | 21dec9f96e4aaccf11c9e69ebb34e40be13eaed7 (diff) | |
parent | b31d0b3b6d0506970adeecd9177e276dd407f418 (diff) | |
download | frameworks_base-d4c18b01cc152f97ea30146d0ad795c05b59e178.zip frameworks_base-d4c18b01cc152f97ea30146d0ad795c05b59e178.tar.gz frameworks_base-d4c18b01cc152f97ea30146d0ad795c05b59e178.tar.bz2 |
am b31d0b3b: am d2e9486b: Merge "re-write the Dialog guide to focus on using DialogFragment" into jb-dev-docs
* commit 'b31d0b3b6d0506970adeecd9177e276dd407f418':
re-write the Dialog guide to focus on using DialogFragment
-rw-r--r-- | docs/html/guide/topics/ui/dialogs.jd | 1234 | ||||
-rwxr-xr-x | docs/html/images/dialog_buttons.png | bin | 3701 -> 0 bytes | |||
-rwxr-xr-x | docs/html/images/dialog_custom.png | bin | 4018 -> 0 bytes | |||
-rwxr-xr-x | docs/html/images/dialog_list.png | bin | 3830 -> 0 bytes | |||
-rwxr-xr-x | docs/html/images/dialog_progress_bar.png | bin | 2562 -> 0 bytes | |||
-rwxr-xr-x | docs/html/images/dialog_progress_spinning.png | bin | 2648 -> 0 bytes | |||
-rwxr-xr-x | docs/html/images/dialog_singlechoicelist.png | bin | 5071 -> 0 bytes | |||
-rw-r--r-- | docs/html/images/ui/dialog_buttons.png | bin | 0 -> 8454 bytes | |||
-rw-r--r-- | docs/html/images/ui/dialog_checkboxes.png | bin | 0 -> 33386 bytes | |||
-rw-r--r-- | docs/html/images/ui/dialog_custom.png | bin | 0 -> 21804 bytes | |||
-rw-r--r-- | docs/html/images/ui/dialog_list.png | bin | 0 -> 13531 bytes | |||
-rw-r--r-- | docs/html/images/ui/dialogs.png | bin | 0 -> 36234 bytes | |||
-rw-r--r-- | docs/html/images/ui/dialogs_regions.png | bin | 0 -> 13355 bytes |
13 files changed, 680 insertions, 554 deletions
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd index d1c24df..62c054a 100644 --- a/docs/html/guide/topics/ui/dialogs.jd +++ b/docs/html/guide/topics/ui/dialogs.jd @@ -1,680 +1,806 @@ page.title=Dialogs -parent.title=User Interface -parent.link=index.html @jd:body + + <div id="qv-wrapper"> <div id="qv"> <h2>In this document</h2> +<ol> + <li><a href="#DialogFragment">Creating a Dialog Fragment</a></li> + <li><a href="#AlertDialog">Building an Alert Dialog</a> <ol> - <li><a href="#ShowingADialog">Showing a Dialog</a></li> - <li><a href="#DismissingADialog">Dismissing a Dialog</a></li> - <li><a href="#AlertDialog">Creating an AlertDialog</a> - <ol> - <li><a href="#AddingButtons">Adding buttons</a></li> - <li><a href="#AddingAList">Adding a list</a></li> - </ol> - </li> - <li><a href="#ProgressDialog">Creating a ProgressDialog</a> - <ol> - <li><a href="#ShowingAProgressBar">Showing a progress bar</a></li> - </ol> - </li> - <li><a href="#CustomDialog">Creating a Custom Dialog</a></li> + <li><a href="#AddingButtons">Adding buttons</a></li> + <li><a href="#AddingAList">Adding a list</a></li> + <li><a href="#CustomLayout">Creating a Custom Layout</a></li> </ol> - - <h2>Key classes</h2> + </li> + <li><a href="#PassingEvents">Passing Events Back to the Dialog's Host</a></li> + <li><a href="#ShowingADialog">Showing a Dialog</a></li> + <li><a href="#FullscreenDialog">Showing a Dialog Fullscreen or as an Embedded Fragment</a> <ol> - <li>{@link android.app.Dialog}</li> - <li>{@link android.app.AlertDialog}</li> - <li>{@link android.app.DialogFragment}</li> + <li><a href="#ActivityAsDialog">Showing an activity as a dialog on large screens</a></li> </ol> + </li> + <li><a href="#DismissingADialog">Dismissing a Dialog</a></li> +</ol> - <h2>Related tutorials</h2> + <h2>Key classes</h2> <ol> - <li><a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello -DatePicker</a></li> - <li><a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello -TimePicker</a></li> + <li>{@link android.app.DialogFragment}</li> + <li>{@link android.app.AlertDialog}</li> </ol> <h2>See also</h2> <ol> - <li><a href="{@docRoot}design/building-blocks/dialogs.html">Android Design: Dialogs</a></li> + <li><a href="{@docRoot}design/building-blocks/dialogs.html">Dialogs design guide</a></li> + <li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> (Date/Time dialogs)</li> </ol> </div> </div> -<p>A dialog is usually a small window that appears in front of the current Activity. -The underlying Activity loses focus and the dialog accepts all user interaction. Dialogs are -normally used for notifications that should interrupt the user and to perform short tasks that -directly relate to the application in progress (such as a progress bar or a login prompt).</p> - -<p>The {@link android.app.Dialog} class is the base class for creating dialogs. However, you -typically should not instantiate a {@link android.app.Dialog} directly. Instead, you should use one -of the following subclasses:</p> -<dl> - <dt>{@link android.app.AlertDialog}</dt> - <dd>A dialog that can manage zero, one, two, or three buttons, and/or a list of - selectable items that can include checkboxes or radio buttons. The AlertDialog - is capable of constructing most dialog user interfaces and is the suggested dialog type. - See <a href="#AlertDialog">Creating an AlertDialog</a> below.</dd> - <dt>{@link android.app.ProgressDialog}</dt> - <dd>A dialog that displays a progress wheel or progress bar. Because it's an extension of - the AlertDialog, it also supports buttons. - See <a href="#ProgressDialog">Creating a ProgressDialog</a> below.</dd> - <dt>{@link android.app.DatePickerDialog}</dt> - <dd>A dialog that allows the user to select a date. See the - <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello DatePicker</a> tutorial.</dd> - <dt>{@link android.app.TimePickerDialog}</dt> - <dd>A dialog that allows the user to select a time. See the - <a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello TimePicker</a> tutorial.</dd> -</dl> - -<p>If you would like to customize your own dialog, you can extend the -base {@link android.app.Dialog} object or any of the subclasses listed above and define a new layout. -See the section on <a href="#CustomDialog">Creating a Custom Dialog</a> below.</p> +<p>A dialog is a small window that prompts the user to +make a decision or enter additional information. A dialog does not fill the screen and is +normally used for modal events that require users to take an action before they can proceed.</p> <div class="note design"> <p><strong>Dialog Design</strong></p> - <p>For design guidelines, read Android Design's <a -href="{@docRoot}design/building-blocks/dialogs.html">Dialogs</a> guide.</p> + <p>For information about how to design your dialogs, including recommendations + for language, read the <a +href="{@docRoot}design/building-blocks/dialogs.html">Dialogs</a> design guide.</p> </div> +<img src="{@docRoot}images/ui/dialogs.png" /> +<p>The {@link android.app.Dialog} class is the base class for dialogs, but you +should avoid instantiating {@link android.app.Dialog} directly. +Instead, use one of the following subclasses:</p> +<dl> + <dt>{@link android.app.AlertDialog}</dt> + <dd>A dialog that can show a title, up to three buttons, a list of + selectable items, or a custom layout.</dd> + <dt>{@link android.app.DatePickerDialog} or {@link android.app.TimePickerDialog}</dt> + <dd>A dialog with a pre-defined UI that allows the user to select a date or time.</dd> +</dl> -<h2 id="ShowingADialog">Showing a Dialog</h2> +<div class="sidebox"> +<h2>Avoid ProgressDialog</h2> +<p>Android includes another dialog class called +{@link android.app.ProgressDialog} that shows a dialog with a progress bar. However, if you +need to indicate loading or indeterminate progress, you should instead follow the design +guidelines for <a href="{@docRoot}design/building-blocks/progress.html">Progress & +Activity</a> and use a {@link android.widget.ProgressBar} in your layout.</p> +</div> -<p>A dialog is always created and displayed as a part of an {@link android.app.Activity}. -You should normally create dialogs from within your Activity's -{@link android.app.Activity#onCreateDialog(int)} callback method. -When you use this callback, the Android system automatically manages the state of -each dialog and hooks them to the Activity, effectively making it the "owner" of each dialog. -As such, each dialog inherits certain properties from the Activity. For example, when a dialog -is open, the Menu key reveals the options menu defined for the Activity and the volume -keys modify the audio stream used by the Activity.</p> - -<p class="note"><strong>Note:</strong> If you decide to create a dialog outside of the -<code>onCreateDialog()</code> method, it will not be attached to an Activity. You can, however, -attach it to an Activity with {@link android.app.Dialog#setOwnerActivity(Activity)}.</p> - -<p>When you want to show a dialog, call -{@link android.app.Activity#showDialog(int)} and pass it an integer that uniquely identifies the -dialog that you want to display.</p> - -<p>When a dialog is requested for the first time, Android calls -{@link android.app.Activity#onCreateDialog(int)} from your Activity, which is -where you should instantiate the {@link android.app.Dialog}. This callback method -is passed the same ID that you passed to {@link android.app.Activity#showDialog(int)}. -After you create the Dialog, return the object at the end of the method.</p> - -<p>Before the dialog is displayed, Android also calls the optional callback method -{@link android.app.Activity#onPrepareDialog(int,Dialog)}. Define this method if you want to change -any properties of the dialog each time it is opened. This method is called -every time a dialog is opened, whereas {@link android.app.Activity#onCreateDialog(int)} is only -called the very first time a dialog is opened. If you don't define -{@link android.app.Activity#onPrepareDialog(int,Dialog) onPrepareDialog()}, then the dialog will -remain the same as it was the previous time it was opened. This method is also passed the dialog's -ID, along with the Dialog object you created in {@link android.app.Activity#onCreateDialog(int) -onCreateDialog()}.</p> - -<p>The best way to define the {@link android.app.Activity#onCreateDialog(int)} and -{@link android.app.Activity#onPrepareDialog(int,Dialog)} callback methods is with a -<em>switch</em> statement that checks the <var>id</var> parameter that's passed into the method. -Each <em>case</em> should check for a unique dialog ID and then create and define the respective Dialog. -For example, imagine a game that uses two different dialogs: one to indicate that the game -has paused and another to indicate that the game is over. First, define an integer ID for -each dialog:</p> -<pre> -static final int DIALOG_PAUSED_ID = 0; -static final int DIALOG_GAMEOVER_ID = 1; -</pre> +<p>These classes define the style and structure for your dialog, but you should +use a {@link android.support.v4.app.DialogFragment} as a container for your dialog. +The {@link android.support.v4.app.DialogFragment} class provides all the controls you +need to create your dialog and manage its appearance, instead of calling methods +on the {@link android.app.Dialog} object.</p> + +<p>Using {@link android.support.v4.app.DialogFragment} to manage the dialog +ensures that it correctly handles lifecycle events +such as when the user presses the <em>Back</em> button or rotates the screen. The {@link +android.support.v4.app.DialogFragment} class also allows you to reuse the dialog's UI as an +embeddable component in a larger UI, just like a traditional {@link +android.support.v4.app.Fragment} (such as when you want the dialog UI to appear differently +on large and small screens).</p> + +<p>The following sections in this guide describe how to use a {@link +android.support.v4.app.DialogFragment} in combination with an {@link android.app.AlertDialog} +object. If you'd like to create a date or time picker, you should instead read the +<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> guide.</p> + +<p class="note"><strong>Note:</strong> +Because the {@link android.app.DialogFragment} class was originally added with +Android 3.0 (API level 11), this document describes how to use the {@link +android.support.v4.app.DialogFragment} class that's provided with the <a +href="{@docRoot}tools/extras/support-library.html">Support Library</a>. By adding this library +to your app, you can use {@link android.support.v4.app.DialogFragment} and a variety of other +APIs on devices running Android 1.6 or higher. If the minimum version your app supports +is API level 11 or higher, then you can use the framework version of {@link +android.app.DialogFragment}, but be aware that the links in this document are for the support +library APIs. When using the support library, +be sure that you import <code>android.support.v4.app.DialogFragment</code> +class and <em>not</em> <code>android.app.DialogFragment</code>.</p> + + +<h2 id="DialogFragment">Creating a Dialog Fragment</h2> + +<p>You can accomplish a wide variety of dialog designs—including +custom layouts and those described in the <a +href="{@docRoot}design/building-blocks/dialogs.html">Dialogs</a> +design guide—by extending +{@link android.support.v4.app.DialogFragment} and creating a {@link android.app.AlertDialog} +in the {@link android.support.v4.app.DialogFragment#onCreateDialog +onCreateDialog()} callback method.</p> + +<p>For example, here's a basic {@link android.app.AlertDialog} that's managed within +a {@link android.support.v4.app.DialogFragment}:</p> -<p>Then, define the {@link android.app.Activity#onCreateDialog(int)} callback with a -switch case for each ID:</p> <pre> -protected Dialog onCreateDialog(int id) { - Dialog dialog; - switch(id) { - case DIALOG_PAUSED_ID: - // do the work to define the pause Dialog - break; - case DIALOG_GAMEOVER_ID: - // do the work to define the game over Dialog - break; - default: - dialog = null; +public class FireMissilesDialog extends DialogFragment { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // Use the Builder class for convenient dialog construction + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(R.string.dialog_fire_missiles) + .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // FIRE ZE MISSILES! + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + // Create the AlertDialog object and return it + return builder.create(); } - return dialog; } </pre> -<p class="note"><strong>Note:</strong> In this example, there's no code inside -the case statements because the procedure for defining your Dialog is outside the scope -of this section. See the section below about <a href="#AlertDialog">Creating an AlertDialog</a>, -offers code suitable for this example.</p> +<div class="figure" style="width:290px;margin:0 0 0 20px"> +<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> +A dialog with a message and two action buttons.</p> +</div> -<p>When it's time to show one of the dialogs, call {@link android.app.Activity#showDialog(int)} -with the ID of a dialog:</p> -<pre> -showDialog(DIALOG_PAUSED_ID); -</pre> +<p>Now, when you create an instance of this class and call {@link +android.support.v4.app.DialogFragment#show show()} on that object, the dialog appears as +shown in figure 1.</p> +<p>The next section describes more about using the {@link android.app.AlertDialog.Builder} +APIs to create the dialog.</p> -<h2 id="DismissingADialog">Dismissing a Dialog</h2> +<p>Depending on how complex your dialog is, you can implement a variety of other callback +methods in the {@link android.support.v4.app.DialogFragment}, including all the basic +<a href="{@docRoot}guide/components/fragments.html#Lifecycle">fragment lifecycle methods</a>. -<p>When you're ready to close your dialog, you can dismiss it by calling -{@link android.app.Dialog#dismiss()} on the Dialog object. -If necessary, you can also call {@link android.app.Activity#dismissDialog(int)} from the -Activity, which effectively calls {@link android.app.Dialog#dismiss()} on the -Dialog for you.</p> - -<p>If you are using {@link android.app.Activity#onCreateDialog(int)} to manage the state -of your dialogs (as discussed in the previous section), then every time your dialog is -dismissed, the state of the Dialog -object is retained by the Activity. If you decide that you will no longer need this object or -it's important that the state is cleared, then you should call -{@link android.app.Activity#removeDialog(int)}. This will remove any internal references -to the object and if the dialog is showing, it will dismiss it.</p> - -<h3>Using dismiss listeners</h3> - -<p>If you'd like your application to perform some procedures the moment that a dialog is dismissed, -then you should attach an on-dismiss listener to your Dialog.</p> - -<p>First define the {@link android.content.DialogInterface.OnDismissListener} interface. -This interface has just one method, -{@link android.content.DialogInterface.OnDismissListener#onDismiss(DialogInterface)}, which -will be called when the dialog is dismissed. -Then simply pass your OnDismissListener implementation to -{@link android.app.Dialog#setOnDismissListener(DialogInterface.OnDismissListener) -setOnDismissListener()}.</p> - -<p>However, note that dialogs can also be "cancelled." This is a special case that indicates -the dialog was explicitly cancelled by the user. This will occur if the user presses the -"back" button to close the dialog, or if the dialog explicitly calls {@link android.app.Dialog#cancel()} -(perhaps from a "Cancel" button in the dialog). When a dialog is cancelled, -the OnDismissListener will still be notified, but if you'd like to be informed that the dialog -was explicitly cancelled (and not dismissed normally), then you should register -an {@link android.content.DialogInterface.OnCancelListener} with -{@link android.app.Dialog#setOnCancelListener(DialogInterface.OnCancelListener) -setOnCancelListener()}.</p> - - -<h2 id="AlertDialog">Creating an AlertDialog</h2> - -<p>An {@link android.app.AlertDialog} is an extension of the {@link android.app.Dialog} -class. It is capable of constructing most dialog user interfaces and is the suggested dialog type. -You should use it for dialogs that use any of the following features:</p> -<ul> - <li>A title</li> - <li>A text message</li> - <li>One, two, or three buttons</li> - <li>A list of selectable items (with optional checkboxes or radio buttons)</li> -</ul> -<p>To create an AlertDialog, use the {@link android.app.AlertDialog.Builder} subclass. -Get a Builder with {@link android.app.AlertDialog.Builder#AlertDialog.Builder(Context)} and -then use the class's public methods to define all of the -AlertDialog properties. After you're done with the Builder, retrieve the -AlertDialog object with {@link android.app.AlertDialog.Builder#create()}.</p> -<p>The following topics show how to define various properties of the AlertDialog using the -AlertDialog.Builder class. If you use any of the following sample code inside your -{@link android.app.Activity#onCreateDialog(int) onCreateDialog()} callback method, -you can return the resulting Dialog object to display the dialog.</p> -<h3 id="AddingButtons">Adding buttons</h3> +<h2 id="AlertDialog">Building an Alert Dialog</h2> + + +<p>The {@link android.app.AlertDialog} class allows you to build a variety of dialog designs and +is often the only dialog class you'll need. +As shown in figure 2, there are three regions of an alert dialog:</p> + +<div class="figure" style="width:311px;margin-top:0"> +<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0"/> +<p class="img-caption"><strong>Figure 2.</strong> The layout of a dialog.</p> +</div> -<img src="{@docRoot}images/dialog_buttons.png" alt="" style="float:right" /> +<ol> +<li><b>Title</b> + <p>This is optional and should be used only when the content area + is occupied by a detailed message, a list, or custom layout. If you need to state + a simple message or question (such as the dialog in figure 1), you don't need a title.</li> +<li><b>Content area</b> + <p>This can display a message, a list, or other custom layout.</p></li> +<li><b>Action buttons</b> + <p>There should be no more than three action buttons in a dialog.</p></li> +</ol> -<p>To create an AlertDialog with side-by-side buttons like the one shown in the screenshot to the right, -use the <code>set...Button()</code> methods:</p> +<p>The {@link android.app.AlertDialog.Builder} +class provides APIs that allow you to create an {@link android.app.AlertDialog} +with these kinds of content, including a custom layout.</p> + +<p>To build an {@link android.app.AlertDialog}:</p> <pre> -AlertDialog.Builder builder = new AlertDialog.Builder(this); -builder.setMessage("Are you sure you want to exit?") - .setCancelable(false) - .setPositiveButton("Yes", new DialogInterface.OnClickListener() { +<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b> +AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + +<b>// 2. Chain together various setter methods to set the dialog characteristics</b> +builder.setMessage(R.string.dialog_message) + .setTitle(R.string.dialog_title); + +<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b> +AlertDialog dialog = builder.create(); +</pre> + +<p>The following topics show how to define various dialog attributes using the +{@link android.app.AlertDialog.Builder} class.</p> + + + + +<h3 id="AddingButtons">Adding buttons</h3> + +<p>To add action buttons like those in figure 2, +call the {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} and +{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()} methods:</p> + +<pre style="clear:right"> +AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); +// Add the buttons +builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - MyActivity.this.finish(); + // User clicked OK button } - }) - .setNegativeButton("No", new DialogInterface.OnClickListener() { + }); +builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); + // User cancelled the dialog } }); -AlertDialog alert = builder.create(); +// Set other dialog properties +... + +// Create the AlertDialog +AlertDialog dialog = builder.create(); </pre> -<p>First, add a message for the dialog with -{@link android.app.AlertDialog.Builder#setMessage(CharSequence)}. Then, begin -method-chaining and set the dialog -to be <em>not cancelable</em> (so the user cannot close the dialog with the back button) -with {@link android.app.AlertDialog.Builder#setCancelable(boolean)}. For each button, -use one of the <code>set...Button()</code> methods, such as -{@link android.app.AlertDialog.Builder#setPositiveButton(CharSequence,DialogInterface.OnClickListener) -setPositiveButton()}, that accepts the name for the button and a +<p>The <code>set...Button()</code> methods require a title for the button (supplied +by a <a href="{@docRoot}guide/topics/resources/string-resource.html">string resource</a>) and a {@link android.content.DialogInterface.OnClickListener} that defines the action to take -when the user selects the button.</p> +when the user presses the button.</p> -<p class="note"><strong>Note:</strong> You can only add one of each button type to the -AlertDialog. That is, you cannot have more than one "positive" button. This limits the number -of possible buttons to three: positive, neutral, and negative. These names are technically irrelevant to the -actual functionality of your buttons, but should help you keep track of which one does what.</p> +<p>There are three different action buttons you can add:</p> +<dl> + <dt>Positive</dt> + <dd>You should use this to accept and continue with the action (the "OK" action).</dd> + <dt>Negative</dt> + <dd>You should use this to cancel the action.</dd> + <dt>Neutral</dt> + <dd>You should use this when the user may not want to proceed with the action, + but doesn't necessarily want to cancel. It appears between the positive and negative + buttons. For example, the action might be "Remind me later."</dd> +</dl> +<p>You can add only one of each button type to an {@link +android.app.AlertDialog}. That is, you cannot have more than one "positive" button.</p> -<h3 id="AddingAList">Adding a list</h3> -<img src="{@docRoot}images/dialog_list.png" alt="" style="float:right" /> -<p>To create an AlertDialog with a list of selectable items like the one shown to the right, -use the <code>setItems()</code> method:</p> +<div class="figure" style="width:290px;margin:0 0 0 40px"> +<img src="{@docRoot}images/ui/dialog_list.png" alt="" /> +<p class="img-caption"><strong>Figure 3.</strong> +A dialog with a title and list.</p> +</div> -<pre> -final CharSequence[] items = {"Red", "Green", "Blue"}; +<h3 id="AddingAList">Adding a list</h3> -AlertDialog.Builder builder = new AlertDialog.Builder(this); -builder.setTitle("Pick a color"); -builder.setItems(items, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show(); - } -}); -AlertDialog alert = builder.create(); -</pre> +<p>There are three kinds of lists available with the {@link android.app.AlertDialog} APIs:</p> +<ul> +<li>A traditional single-choice list</li> +<li>A persistent single-choice list (radio buttons)</li> +<li>A persistent multiple-choice list (checkboxes)</li> +</ul> -<p>First, add a title to the dialog with -{@link android.app.AlertDialog.Builder#setTitle(CharSequence)}. -Then, add a list of selectable items with -{@link android.app.AlertDialog.Builder#setItems(CharSequence[],DialogInterface.OnClickListener) -setItems()}, which accepts the array of items to display and a -{@link android.content.DialogInterface.OnClickListener} that defines the action to take -when the user selects an item.</p> +<p>To create a single-choice list like the one in figure 3, +use the {@link android.app.AlertDialog.Builder#setItems setItems()} method:</p> + +<pre style="clear:right"> +@Override +public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.pick_color); + .setItems(R.array.colors_array, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // The 'which' argument contains the index position + // of the selected item + } + }); + return builder.create(); +} +</pre> +<p>Because the list appears in the dialog's content area, +the dialog cannot show both a message and a list and you should set a title for the +dialog with {@link android.app.AlertDialog.Builder#setTitle setTitle()}. +To specify the items for the list, call {@link +android.app.AlertDialog.Builder#setItems setItems()}, passing an array. +Alternatively, you can specify a list using {@link +android.app.AlertDialog.Builder#setAdapter setAdapter()}. This allows you to back the list +with dynamic data (such as from a database) using a {@link android.widget.ListAdapter}.</p> + +<p>If you choose to back your list with a {@link android.widget.ListAdapter}, +always use a {@link android.support.v4.content.Loader} so that the content loads +asynchronously. This is described further in +<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts +with an Adapter</a> and the <a href="{@docRoot}guide/components/loaders.html">Loaders</a> +guide.</p> + +<p class="note"><strong>Note:</strong> By default, touching a list item dismisses the dialog, +unless you're using one of the following persistent choice lists.</p> + +<div class="figure" style="width:290px;margin:-30px 0 0 40px"> +<img src="{@docRoot}images/ui/dialog_checkboxes.png" /> +<p class="img-caption"><strong>Figure 4.</strong> +A list of multiple-choice items.</p> +</div> -<h4>Adding checkboxes and radio buttons</h4> -<img src="{@docRoot}images/dialog_singlechoicelist.png" alt="" style="float:right" /> +<h4 id="Checkboxes">Adding a persistent multiple-choice or single-choice list</h4> -<p>To create a list of multiple-choice items (checkboxes) or -single-choice items (radio buttons) inside the dialog, use the +<p>To add a list of multiple-choice items (checkboxes) or +single-choice items (radio buttons), use the {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, -DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} and -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) -setSingleChoiceItems()} methods, respectively. -If you create one of these selectable lists in the -{@link android.app.Activity#onCreateDialog(int) onCreateDialog()} callback method, -Android manages the state of the list for you. As long as the Activity is active, -the dialog remembers the items that were previously selected, but when the user exits the -Activity, the selection is lost. - -<p class="note"><strong>Note:</strong> To save the selection when the user leaves or -pauses the Activity, you must properly save and restore the setting throughout -the <a href="{@docRoot}guide/components/activities.html#Lifecycle">activity lifecycle</a>. -To permanently save the selections, even when the Activity process is completely shutdown, -you need to save the settings -with one of the <a href="{@docRoot}guide/topics/data/data-storage.html">Data -Storage</a> techniques.</p> - -<p>To create an AlertDialog with a list of single-choice items like the one shown to the right, -use the same code from the previous example, but replace the <code>setItems()</code> method with +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} or {@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) -setSingleChoiceItems()}:</p> +setSingleChoiceItems()} methods, respectively.</p> + +<p>For example, here's how you can create a multiple-choice list like the +one shown in figure 4 that saves the selected +items in an {@link java.util.ArrayList}:</p> + +<pre style="clear:right"> +@Override +public Dialog onCreateDialog(Bundle savedInstanceState) { + mSelectedItems = new ArrayList(); // Where we track the selected items + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Set the dialog title + builder.setTitle(R.string.pick_toppings) + // Specify the list array, the items to be selected by default (null for none), + // and the listener through which to receive callbacks when items are selected + .setMultiChoiceItems(R.array.toppings, null, + new DialogInterface.OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, int which, + boolean isChecked) { + if (isChecked) { + // If the user checked the item, add it to the selected items + mSelectedItems.add(which); + } else if (mSelectedItems.contains(which)) { + // Else, if the item is already in the array, remove it + mSelectedItems.remove(Integer.valueOf(which)); + } + } + }) + // Set the action buttons + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // User clicked OK, so save the mSelectedItems results somewhere + // or return them to the component that opened the dialog + ... + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + ... + } + }); + + return builder.create(); +} +</pre> + +<p>Although both a traditional list and a list with radio buttons +provide a "single choice" action, you should use {@link +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +setSingleChoiceItems()} if you want to persist the user's choice. +That is, if opening the dialog again later should indicate what the user's current choice is, +then you create a list with radio buttons.</p> + + -<pre> -final CharSequence[] items = {"Red", "Green", "Blue"}; -AlertDialog.Builder builder = new AlertDialog.Builder(this); -builder.setTitle("Pick a color"); -builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show(); - } -}); -AlertDialog alert = builder.create(); -</pre> -<p>The second parameter in the -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(CharSequence[],int,DialogInterface.OnClickListener) -setSingleChoiceItems()} method is an integer value for the <var>checkedItem</var>, which indicates the -zero-based list position of the default selected item. Use "-1" to indicate that no item should be -selected by default.</p> +<h3 id="CustomLayout">Creating a Custom Layout</h3> +<div class="figure" style="width:290px;margin:-30px 0 0 40px"> +<img src="{@docRoot}images/ui/dialog_custom.png" alt="" /> +<p class="img-caption"><strong>Figure 5.</strong> A custom dialog layout.</p> +</div> + +<p>If you want a custom layout in a dialog, create a layout and add it to an +{@link android.app.AlertDialog} by calling {@link +android.app.AlertDialog.Builder#setView setView()} on your {@link +android.app.AlertDialog.Builder} object.</p> + +<p>By default, the custom layout fills the dialog window, but you can still +use {@link android.app.AlertDialog.Builder} methods to add buttons and a title.</p> -<h2 id="ProgressDialog">Creating a ProgressDialog</h2> +<p>For example, here's the layout file for the dialog in Figure 5:</p> -<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" /> +<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p> +<pre> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + <ImageView + android:src="@drawable/header_logo" + android:layout_width="match_parent" + android:layout_height="64dp" + android:scaleType="center" + android:background="#FFFFBB33" + android:contentDescription="@string/app_name" /> + <EditText + android:id="@+id/username" + android:inputType="textEmailAddress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginLeft="4dp" + android:layout_marginRight="4dp" + android:layout_marginBottom="4dp" + android:hint="@string/username" /> + <EditText + android:id="@+id/password" + android:inputType="textPassword" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="4dp" + android:layout_marginLeft="4dp" + android:layout_marginRight="4dp" + android:layout_marginBottom="16dp" + android:fontFamily="sans-serif" + android:hint="@string/password"/> +</LinearLayout> +</pre> -<p>A {@link android.app.ProgressDialog} is an extension of the {@link android.app.AlertDialog} -class that can display a progress animation in the form of a spinning wheel, for a task with -progress that's undefined, or a progress bar, for a task that has a defined progression. -The dialog can also provide buttons, such as one to cancel a download.</p> +<p class="note"><strong>Tip:</strong> By default, when you set an {@link android.widget.EditText} +element to use the {@code "textPassword"} input type, the font family is set to monospace, so +you should change its font family to {@code "sans-serif"} so that both text fields use +a matching font style.</p> -<p>Opening a progress dialog can be as simple as calling -{@link android.app.ProgressDialog#show(Context,CharSequence,CharSequence) -ProgressDialog.show()}. For example, the progress dialog shown to the right can be -easily achieved without managing the dialog through the -{@link android.app.Activity#onCreateDialog(int)} callback, -as shown here:</p> +<p>To inflate the layout in your {@link android.support.v4.app.DialogFragment}, +get a {@link android.view.LayoutInflater} with +{@link android.app.Activity#getLayoutInflater()} and call +{@link android.view.LayoutInflater#inflate inflate()}, where the first parameter +is the layout resource ID and the second parameter is a parent view for the layout. +You can then call {@link android.app.AlertDialog#setView setView()} +to place the layout in the dialog.</p> <pre> -ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "", - "Loading. Please wait...", true); +@Override +public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Get the layout inflater + LayoutInflater inflater = getActivity().getLayoutInflater(); + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + builder.setView(inflater.inflate(R.layout.dialog_signin, null)) + // Add action buttons + .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // sign in the user ... + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + NoticeDialog.this.getDialog().cancel(); + } + }); + return builder.create(); +} </pre> -<p>The first parameter is the application {@link android.content.Context}, -the second is a title for the dialog (left empty), the third is the message, -and the last parameter is whether the progress -is indeterminate (this is only relevant when creating a progress bar, which is -discussed in the next section). -</p> +<div class="note"> +<p><strong>Tip:</strong> If you want a custom dialog, +you can instead display an {@link android.app.Activity} as a dialog +instead of using the {@link android.app.Dialog} APIs. Simply create an activity and set its theme to +{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog} +in the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a> manifest element:</p> -<p>The default style of a progress dialog is the spinning wheel. -If you want to create a progress bar that shows the loading progress with granularity, -some more code is required, as discussed in the next section.</p> +<pre> +<activity android:theme="@android:style/Theme.Holo.Dialog" > +</pre> +<p>That's it. The activity now displays in a dialog window instead of fullscreen.</p> +</div> -<h3 id="ShowingAProgressBar">Showing a progress bar</h3> -<img src="/images/dialog_progress_bar.png" alt="" style="float:right" /> +<h2 id="PassingEvents">Passing Events Back to the Dialog's Host</h2> -<p>To show the progression with an animated progress bar:</p> +<p>When the user touches one of the dialog's action buttons or selects an item from its list, +your {@link android.support.v4.app.DialogFragment} might perform the necessary +action itself, but often you'll want to deliver the event to the activity or fragment that +opened the dialog. To do this, define an interface with a method for each type of click event, +then implement that interface in the host component that will +receive the action events from the dialog.</p> -<ol> - <li>Initialize the - ProgressDialog with the class constructor, - {@link android.app.ProgressDialog#ProgressDialog(Context)}.</li> - <li>Set the progress style to "STYLE_HORIZONTAL" with - {@link android.app.ProgressDialog#setProgressStyle(int)} and - set any other properties, such as the message.</li> - <li>When you're ready to show the dialog, call - {@link android.app.Dialog#show()} or return the ProgressDialog from the - {@link android.app.Activity#onCreateDialog(int)} callback.</li> - <li>You can increment the amount of progress displayed - in the bar by calling either {@link android.app.ProgressDialog#setProgress(int)} with a value for - the total percentage completed so far or {@link android.app.ProgressDialog#incrementProgressBy(int)} - with an incremental value to add to the total percentage completed so far.</li> -</ol> +<p>For example, here's a {@link android.support.v4.app.DialogFragment} that defines an +interface through which it delivers the events back to the host activity:</p> -<p>For example, your setup might look like this:</p> <pre> -ProgressDialog progressDialog; -progressDialog = new ProgressDialog(mContext); -progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); -progressDialog.setMessage("Loading..."); -progressDialog.setCancelable(false); +public class NoticeDialog extends DialogFragment { + + /* The activity that creates an instance of this dialog fragment must + * implement this interface in order to receive event callbacks. + * Each method passes the DialogFragment in case the host needs to query it. */ + public interface NoticeDialogListener { + public void onDialogPositiveClick(DialogFragment dialog); + public void onDialogNegativeClick(DialogFragment dialog); + } + + // Use this instance of the interface to deliver action events + static NoticeDialogListener mListener; + + /* Call this to instantiate a new NoticeDialog. + * @param activity The activity hosting the dialog, which must implement the + * NoticeDialogListener to receive event callbacks. + * @returns A new instance of NoticeDialog. + * @throws ClassCastException if the host activity does not + * implement NoticeDialogListener + */ + public static NoticeDialog newInstance(Activity activity) { + // Verify that the host activity implements the callback interface + try { + // Instantiate the NoticeDialogListener so we can send events with it + mListener = (NoticeDialogListener) activity; + } catch (ClassCastException e) { + // The activity doesn't implement the interface, throw exception + throw new ClassCastException(activity.toString() + + " must implement NoticeDialogListener"); + } + NoticeDialog frag = new NoticeDialog(); + return frag; + } + + ... +} </pre> -<p>The setup is simple. Most of the code needed to create a progress dialog is actually -involved in the process that updates it. You might find that it's -necessary to create a second thread in your application for this work and then report the progress -back to the Activity's UI thread with a {@link android.os.Handler} object. -If you're not familiar with using additional -threads with a Handler, see the example Activity below that uses a second thread to -increment a progress dialog managed by the Activity.</p> - -<script type="text/javascript"> -function toggleDiv(link) { - var toggleable = $(link).parent(); - if (toggleable.hasClass("closed")) { - $(".toggleme", toggleable).slideDown("fast"); - toggleable.removeClass("closed"); - toggleable.addClass("open"); - $(".toggle-img", toggleable).attr("title", "hide").attr("src", "/assets/images/triangle-opened.png"); - } else { - $(".toggleme", toggleable).slideUp("fast"); - toggleable.removeClass("open"); - toggleable.addClass("closed"); - $(".toggle-img", toggleable).attr("title", "show").attr("src", "/assets/images/triangle-closed.png"); - } - return false; -} -</script> -<style> -.toggleme { - padding:0 0 1px 0; -} -.toggleable a { - text-decoration:none; -} -.toggleable.closed .toggleme { - display:none; -} -#jd-content .toggle-img { - margin:0; -} -</style> - -<div class="toggleable closed"> - <a href="#" onclick="return toggleDiv(this)"> - <img src="/assets/images/triangle-closed.png" class="toggle-img" /> - <strong>Example ProgressDialog with a second thread</strong></a> - <div class="toggleme"> - <p>This example uses a second thread to track the progress of a process (which actually just -counts up to 100). The thread sends a {@link android.os.Message} back to the main -Activity through a {@link android.os.Handler} each time progress is made. The main Activity then updates the -ProgressDialog.</p> +<p>The activity hosting the dialog creates and shows an instance of the dialog +by calling {@code NoticeDialog.newInstance()} and receives the dialog's +events through an implementation of the {@code NoticeDialogListener} interface:</p> <pre> -package com.example.progressdialog; - -import android.app.Activity; -import android.app.Dialog; -import android.app.ProgressDialog; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -public class NotificationTest extends Activity { - static final int PROGRESS_DIALOG = 0; - Button button; - ProgressThread progressThread; - ProgressDialog progressDialog; - - /** Called when the activity is first created. */ - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - // Setup the button that starts the progress dialog - button = (Button) findViewById(R.id.progressDialog); - button.setOnClickListener(new OnClickListener(){ - public void onClick(View v) { - showDialog(PROGRESS_DIALOG); - } - }); +public class MainActivity extends FragmentActivity + implements NoticeDialog.NoticeDialogListener{ + ... + + public void showNoticeDialog() { + // Create an instance of the dialog fragment and show it + DialogFragment dialog = NoticeDialog.newInstance(this); + dialog.show(getSupportFragmentManager(), "NoticeDialog"); } - - protected Dialog onCreateDialog(int id) { - switch(id) { - case PROGRESS_DIALOG: - progressDialog = new ProgressDialog(NotificationTest.this); - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - progressDialog.setMessage("Loading..."); - return progressDialog; - default: - return null; - } + + @Override + public void onDialogPositiveClick(DialogFragment dialog) { + // User touched the dialog's positive button + ... } @Override - protected void onPrepareDialog(int id, Dialog dialog) { - switch(id) { - case PROGRESS_DIALOG: - progressDialog.setProgress(0); - progressThread = new ProgressThread(handler); - progressThread.start(); + public void onDialogNegativeClick(DialogFragment dialog) { + // User touched the dialog's negative button + ... } +} +</pre> - // Define the Handler that receives messages from the thread and update the progress - final Handler handler = new Handler() { - public void handleMessage(Message msg) { - int total = msg.arg1; - progressDialog.setProgress(total); - if (total >= 100){ - dismissDialog(PROGRESS_DIALOG); - progressThread.setState(ProgressThread.STATE_DONE); - } - } - }; - - /** Nested class that performs progress calculations (counting) */ - private class ProgressThread extends Thread { - Handler mHandler; - final static int STATE_DONE = 0; - final static int STATE_RUNNING = 1; - int mState; - int total; - - ProgressThread(Handler h) { - mHandler = h; - } - - public void run() { - mState = STATE_RUNNING; - total = 0; - while (mState == STATE_RUNNING) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Log.e("ERROR", "Thread Interrupted"); - } - Message msg = mHandler.obtainMessage(); - msg.arg1 = total; - mHandler.sendMessage(msg); - total++; - } - } - - /* sets the current state for the thread, - * used to stop the thread */ - public void setState(int state) { - mState = state; - } +<p>Because the host activity implements the {@code NoticeDialogListener}—which is +enforced by the {@code newInstance()} method shown above—the dialog fragment can use the +interface callback methods to deliver click events to the activity:</p> + +<pre> +public class NoticeDialog extends DialogFragment { + ... + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // Build the dialog and set up the button click handlers + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(R.string.dialog_fire_missiles) + .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // Send the positive button event back to the host activity + mListener.onDialogPositiveClick(NoticeDialog.this); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // Send the negative button event back to the host activity + mListener.onDialogPositiveClick(NoticeDialog.this); + } + }); + return builder.create(); } } </pre> - </div> <!-- end toggleme --> -</div> <!-- end toggleable --> -<h2 id="CustomDialog">Creating a Custom Dialog</h2> -<img src="{@docRoot}images/dialog_custom.png" alt="" style="float:right" /> -<p>If you want a customized design for a dialog, you can create your own layout -for the dialog window with layout and widget elements. -After you've defined your layout, pass the root View object or -layout resource ID to {@link android.app.Dialog#setContentView(View)}.</p> +<h2 id="ShowingADialog">Showing a Dialog</h2> -<p>For example, to create the dialog shown to the right:</p> +<p>When you want to show your dialog, create an instance of your {@link +android.support.v4.app.DialogFragment} and call {@link android.support.v4.app.DialogFragment#show +show()}, passing the {@link android.support.v4.app.FragmentManager} and a tag name +for the dialog fragment.</p> + +<p>You can get the {@link android.support.v4.app.FragmentManager} by calling +{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} from +the {@link android.support.v4.app.FragmentActivity} or {@link +android.support.v4.app.Fragment#getFragmentManager()} from a {@link +android.support.v4.app.Fragment}. For example:</p> -<ol> - <li>Create an XML layout saved as <code>custom_dialog.xml</code>: <pre> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/layout_root" - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:padding="10dp" - > - <ImageView android:id="@+id/image" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_marginRight="10dp" - /> - <TextView android:id="@+id/text" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:textColor="#FFF" - /> -</LinearLayout> +public void confirmFireMissiles() { + DialogFragment newFragment = FireMissilesDialog.newInstance(this); + newFragment.show(getSupportFragmentManager(), "missiles"); +} </pre> - <p>This XML defines an {@link android.widget.ImageView} and a {@link android.widget.TextView} - inside a {@link android.widget.LinearLayout}.</p> - <li>Set the above layout as the dialog's content view and define the content - for the ImageView and TextView elements:</p> +<p>The second argument, {@code "missiles"}, is a unique tag name that the system uses to save +and restore the fragment state when necessary. The tag also allows you to get a handle to +the fragment by calling {@link android.support.v4.app.FragmentManager#findFragmentByTag +findFragmentByTag()}.</p> + + + + +<h2 id="FullscreenDialog">Showing a Dialog Fullscreen or as an Embedded Fragment</h2> + +<p>You might have a UI design in which you want a piece of the UI to appear as a dialog in some +situations, but as a full screen or embedded fragment in others (perhaps depending on whether +the device is a large screen or small screen). The {@link android.support.v4.app.DialogFragment} +class offers you this flexibility because it can still behave as an embeddable {@link +android.support.v4.app.Fragment}.</p> + +<p>However, you cannot use {@link android.app.AlertDialog.Builder AlertDialog.Builder} +or other {@link android.app.Dialog} objects to build the dialog in this case. If +you want the {@link android.support.v4.app.DialogFragment} to be +embeddable, you must define the dialog's UI in a layout, then load the layout in the +{@link android.support.v4.app.DialogFragment#onCreateView +onCreateView()} callback.</p> + +<p>Here's an example {@link android.support.v4.app.DialogFragment} that can appear as either a +dialog or an embeddable fragment (using a layout named <code>purchase_items.xml</code>):</p> + <pre> -Context mContext = getApplicationContext(); -Dialog dialog = new Dialog(mContext); +public class CustomLayoutDialog extends DialogFragment { + /** The system calls this to get the DialogFragment's layout, regardless + of whether it's being displayed as a dialog or an embedded fragment. */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout to use as dialog or embedded fragment + return inflater.inflate(R.layout.purchase_items, container, false); + } + + /** The system calls this only when creating the layout in a dialog. */ + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + // The only reason you might override this method when using onCreateView() is + // to modify any dialog characteristics. For example, the dialog includes a + // title by default, but your custom layout might not need it. So here you can + // remove the dialog title, but you must call the superclass to get the Dialog. + Dialog dialog = super.onCreateDialog(savedInstanceState); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + return dialog; + } +} +</pre> -dialog.setContentView(R.layout.custom_dialog); -dialog.setTitle("Custom Dialog"); +<p>And here's some code that decides whether to show the fragment as a dialog +or a fullscreen UI, based on the screen size:</p> -TextView text = (TextView) dialog.findViewById(R.id.text); -text.setText("Hello, this is a custom dialog!"); -ImageView image = (ImageView) dialog.findViewById(R.id.image); -image.setImageResource(R.drawable.android); +<pre> +public void showDialog() { + FragmentManager fragmentManager = getSupportFragmentManager(); + CustomLayoutDialog newFragment = new CustomLayoutDialog(); + + if (mIsLargeLayout) { + // The device is using a large layout, so show the fragment as a dialog + newFragment.show(fragmentManager, "dialog"); + } else { + // The device is smaller, so show the fragment fullscreen + FragmentTransaction transaction = fragmentManager.beginTransaction(); + // For a little polish, specify a transition animation + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); + // To make it fullscreen, use the 'content' root view as the container + // for the fragment, which is always the root view for the activity + transaction.add(android.R.id.content, newFragment) + .addToBackStack(null).commit(); + } +} </pre> - <p>After you instantiate the Dialog, set your custom layout as the dialog's content view with - {@link android.app.Dialog#setContentView(int)}, passing it the layout resource ID. - Now that the Dialog has a defined layout, you can capture View objects from the layout with - {@link android.app.Dialog#findViewById(int)} and modify their content.</p> - </li> +<p>For more information about performing fragment transactions, see the +<a href="{@docRoot}guide/components/fragments.html">Fragments</a> guide.</p> - <li>That's it. You can now show the dialog as described in - <a href="#ShowingADialog">Showing A Dialog</a>.</li> -</ol> +<p>In this example, the <code>mIsLargeLayout</code> boolean specifies whether the current device +should use the app's large layout design (and thus show this fragment as a dialog, rather +than fullscreen). The best way to set this kind of boolean is to declare a +<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">bool resource value</a> +with an <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources" +>alternative resource</a> value for different screen sizes. For example, here are two +versions of the bool resource for different screen sizes:</p> -<p>A dialog made with the base Dialog class must have a title. If you don't call -{@link android.app.Dialog#setTitle(CharSequence) setTitle()}, then the space used for the title -remains empty, but still visible. If you don't want -a title at all, then you should create your custom dialog using the -{@link android.app.AlertDialog} class. However, because an AlertDialog is created easiest with -the {@link android.app.AlertDialog.Builder} class, you do not have access to the -{@link android.app.Dialog#setContentView(int)} method used above. Instead, you must use -{@link android.app.AlertDialog.Builder#setView(View)}. This method accepts a {@link android.view.View} object, -so you need to inflate the layout's root View object from -XML.</p> - -<p>To inflate the XML layout, retrieve the {@link android.view.LayoutInflater} with -{@link android.app.Activity#getLayoutInflater()} -(or {@link android.content.Context#getSystemService(String) getSystemService()}), -and then call -{@link android.view.LayoutInflater#inflate(int, ViewGroup)}, where the first parameter -is the layout resource ID and the second is the ID of the root View. At this point, you can use -the inflated layout to find View objects in the layout and define the content for the -ImageView and TextView elements. Then instantiate the AlertDialog.Builder and set the -inflated layout for the dialog with {@link android.app.AlertDialog.Builder#setView(View)}.</p> - -<p>Here's an example, creating a custom layout in an AlertDialog:</p> +<p class="code-caption">res/values/bools.xml</p> +<pre> +<!-- Default boolean values --> +<resources> + <bool name="large_layout">false</bool> +</resources> +</pre> + +<p class="code-caption">res/values-large/bools.xml</p> +<pre> +<!-- Large screen boolean values --> +<resources> + <bool name="large_layout">true</bool> +</resources> +</pre> + +<p>Then you can initialize the {@code mIsLargeLayout} value during the activity's +{@link android.app.Activity#onCreate onCreate()} method:</p> + +<pre> +boolean mIsLargeLayout; + +@Override +public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + mIsLargeLayout = getResources().getBoolean(R.bool.large_layout); +} +</pre> + + + +<h3 id="ActivityAsDialog">Showing an activity as a dialog on large screens</h3> + +<p>Instead of showing a dialog as a fullscreen UI when on small screens, you can accomplish +the same result by showing an {@link android.app.Activity} as a dialog when on +large screens. Which approach you choose depends on your app design, but +showing an activity as a dialog is often useful when your app is already designed for small +screens and you'd like to improve the experience on tablets by showing a short-lived activity +as a dialog.</p> + +<p>To show an activity as a dialog only when on large screens, +apply the {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge} +theme to the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a> manifest element:</p> <pre> -AlertDialog.Builder builder; -AlertDialog alertDialog; - -Context mContext = getApplicationContext(); -LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE); -View layout = inflater.inflate(R.layout.custom_dialog, - (ViewGroup) findViewById(R.id.layout_root)); - -TextView text = (TextView) layout.findViewById(R.id.text); -text.setText("Hello, this is a custom dialog!"); -ImageView image = (ImageView) layout.findViewById(R.id.image); -image.setImageResource(R.drawable.android); - -builder = new AlertDialog.Builder(mContext); -builder.setView(layout); -alertDialog = builder.create(); +<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" > </pre> -<p>Using an AlertDialog for your custom layout lets you -take advantage of built-in AlertDialog features like managed buttons, -selectable lists, a title, an icon and so on.</p> +<p>For more information about styling your activities with themes, see the <a +href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a> guide.</p> + -<p>For more information, refer to the reference documentation for the -{@link android.app.Dialog} and {@link android.app.AlertDialog.Builder} -classes.</p> +<h2 id="DismissingADialog">Dismissing a Dialog</h2> + +<p>When the user touches any of the action buttons created with an +{@link android.app.AlertDialog.Builder}, the system dismisses the dialog for you.</p> + +<p>The system also dismisses the dialog when the user touches an item in a dialog list, except +when the list uses radio buttons or checkboxes. Otherwise, you can manually dismiss your dialog +by calling {@link android.support.v4.app.DialogFragment#dismiss()} on your {@link +android.support.v4.app.DialogFragment}.</p> + +<p>In case you need to perform certain +actions when the dialog goes away, you can implement the {@link +android.support.v4.app.DialogFragment#onDismiss onDismiss()} method in your {@link +android.support.v4.app.DialogFragment}.</p> + +<p>You can also <em>cancel</em> a dialog. This is a special event that indicates the user +explicitly left the dialog without completing the task. This occurs if the user presses the +<em>Back</em> button, touches the screen outside the dialog area, +or if you explicitly call {@link android.app.Dialog#cancel()} on the {@link +android.app.Dialog} (such as in response to a "Cancel" button in the dialog).</p> + +<p>As shown in the example above, you can respond to the cancel event by implementing +{@link android.support.v4.app.DialogFragment#onCancel onCancel()} in your {@link +android.support.v4.app.DialogFragment} class.</p> + +<p class="note"><strong>Note:</strong> The system calls +{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} upon each event that +invokes the {@link android.support.v4.app.DialogFragment#onCancel onCancel()} callback. However, +if you call {@link android.app.Dialog#dismiss Dialog.dismiss()} or {@link +android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()}, +the system calls {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>but +not</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. So you should generally +call {@link android.support.v4.app.DialogFragment#dismiss dismiss()} when the user presses the +<em>positive</em> button in your dialog in order to remove the dialog from view.</p> diff --git a/docs/html/images/dialog_buttons.png b/docs/html/images/dialog_buttons.png Binary files differdeleted file mode 100755 index 81aaec4..0000000 --- a/docs/html/images/dialog_buttons.png +++ /dev/null diff --git a/docs/html/images/dialog_custom.png b/docs/html/images/dialog_custom.png Binary files differdeleted file mode 100755 index b2523fd..0000000 --- a/docs/html/images/dialog_custom.png +++ /dev/null diff --git a/docs/html/images/dialog_list.png b/docs/html/images/dialog_list.png Binary files differdeleted file mode 100755 index f2736bf..0000000 --- a/docs/html/images/dialog_list.png +++ /dev/null diff --git a/docs/html/images/dialog_progress_bar.png b/docs/html/images/dialog_progress_bar.png Binary files differdeleted file mode 100755 index 3e74419..0000000 --- a/docs/html/images/dialog_progress_bar.png +++ /dev/null diff --git a/docs/html/images/dialog_progress_spinning.png b/docs/html/images/dialog_progress_spinning.png Binary files differdeleted file mode 100755 index 501f4802..0000000 --- a/docs/html/images/dialog_progress_spinning.png +++ /dev/null diff --git a/docs/html/images/dialog_singlechoicelist.png b/docs/html/images/dialog_singlechoicelist.png Binary files differdeleted file mode 100755 index 90629f0..0000000 --- a/docs/html/images/dialog_singlechoicelist.png +++ /dev/null diff --git a/docs/html/images/ui/dialog_buttons.png b/docs/html/images/ui/dialog_buttons.png Binary files differnew file mode 100644 index 0000000..ed952a1 --- /dev/null +++ b/docs/html/images/ui/dialog_buttons.png diff --git a/docs/html/images/ui/dialog_checkboxes.png b/docs/html/images/ui/dialog_checkboxes.png Binary files differnew file mode 100644 index 0000000..8f272e5 --- /dev/null +++ b/docs/html/images/ui/dialog_checkboxes.png diff --git a/docs/html/images/ui/dialog_custom.png b/docs/html/images/ui/dialog_custom.png Binary files differnew file mode 100644 index 0000000..244473b --- /dev/null +++ b/docs/html/images/ui/dialog_custom.png diff --git a/docs/html/images/ui/dialog_list.png b/docs/html/images/ui/dialog_list.png Binary files differnew file mode 100644 index 0000000..437fc74 --- /dev/null +++ b/docs/html/images/ui/dialog_list.png diff --git a/docs/html/images/ui/dialogs.png b/docs/html/images/ui/dialogs.png Binary files differnew file mode 100644 index 0000000..d45b0b5 --- /dev/null +++ b/docs/html/images/ui/dialogs.png diff --git a/docs/html/images/ui/dialogs_regions.png b/docs/html/images/ui/dialogs_regions.png Binary files differnew file mode 100644 index 0000000..2bfc1a4 --- /dev/null +++ b/docs/html/images/ui/dialogs_regions.png |