summaryrefslogtreecommitdiffstats
path: root/core/java/android/app
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-08-20 18:26:01 -0700
committerDianne Hackborn <hackbod@google.com>2010-08-20 18:32:41 -0700
commit727782053ced0cac5beadc2c7ee9382d0f1ba1f5 (patch)
tree211c306b0f7a118a801813339f17f24bd96042de /core/java/android/app
parent76dd2ce960fea031887bf0a1a26d0ea761812f3e (diff)
downloadframeworks_base-727782053ced0cac5beadc2c7ee9382d0f1ba1f5.zip
frameworks_base-727782053ced0cac5beadc2c7ee9382d0f1ba1f5.tar.gz
frameworks_base-727782053ced0cac5beadc2c7ee9382d0f1ba1f5.tar.bz2
Work on DialogFragment and docs.
- DialogFragment now has an option to not show a dialog, so you can use your UI somewhere else. - Deprecated show() versions that were tied to activities. - Added documentation to DialogFragment class. - Added documentation to onSaveInstanceState() to explain how the time it is called is different than Activity's version. - Fixed some java doc warnings. Change-Id: If026744c368e2443030d2d9e0a9c808d820857df
Diffstat (limited to 'core/java/android/app')
-rw-r--r--core/java/android/app/DialogFragment.java199
-rw-r--r--core/java/android/app/Fragment.java19
2 files changed, 202 insertions, 16 deletions
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index 50e7421..e8dfac9 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -36,6 +36,102 @@ import android.view.WindowManager;
* content of the dialog. Alternatively, they can override
* {@link #onCreateDialog(Bundle)} to create an entirely custom dialog, such
* as an AlertDialog, with its own content.
+ *
+ * <p>Topics covered here:
+ * <ol>
+ * <li><a href="#Lifecycle">Lifecycle</a>
+ * <li><a href="#BasicDialog">Basic Dialog</a>
+ * <li><a href="#AlertDialog">Alert Dialog</a>
+ * <li><a href="#DialogOrEmbed">Selecting Between Dialog or Embedding</a>
+ * </ol>
+ *
+ * <a name="Lifecycle"></a>
+ * <h3>Lifecycle</h3>
+ *
+ * <p>DialogFragment does various things to keep the fragment's lifecycle
+ * driving it, instead of the Dialog. Note that dialogs are generally
+ * autonomous entities -- they are their own window, receiving their own
+ * input events, and often deciding on their own when to disappear (by
+ * receiving a back key event or the user clicking on a button).
+ *
+ * <p>DialogFragment needs to ensure that what is happening with the Fragment
+ * and Dialog states remains consistent. To do this, it watches for dismiss
+ * events from the dialog and takes are of removing its own state when they
+ * happen. This means you should use {@link #show(FragmentManager, String)}
+ * or {@link #show(FragmentTransaction, String)} to add an instance of
+ * DialogFragment to your UI, as these keep track of how DialogFragment should
+ * remove itself when the dialog is dismissed.
+ *
+ * <a name="BasicDialog"></a>
+ * <h3>Basic Dialog</h3>
+ *
+ * <p>The simplest use of DialogFragment is as a floating container for the
+ * fragment's view hierarchy. A simple implementation may look like this:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialog.java
+ * dialog}
+ *
+ * <p>An example showDialog() method on the Activity could be:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialog.java
+ * add_dialog}
+ *
+ * <p>This removes any currently shown dialog, creates a new DialogFragment
+ * with an argument, and shows it as a new state on the back stack. When the
+ * transaction is popped, the current DialogFragment and its Dialog will be
+ * destroyed, and the previous one (if any) re-shown. Note that in this case
+ * DialogFragment will take care of popping the transaction of the Dialog
+ * is dismissed separately from it.
+ *
+ * <a name="AlertDialog"></a>
+ * <h3>Alert Dialog</h3>
+ *
+ * <p>Instead of (or in addition to) implementing {@link #onCreateView} to
+ * generate the view hierarchy inside of a dialog, you may implement
+ * {@link #onCreateDialog(Bundle)} to create your own custom Dialog object.
+ *
+ * <p>This is most useful for creating an {@link AlertDialog}, allowing you
+ * to display standard alerts to the user that are managed by a fragment.
+ * A simple example implementation of this is:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.java
+ * dialog}
+ *
+ * <p>The activity creating this fragment may have the following methods to
+ * show the dialog and receive results from it:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.java
+ * activity}
+ *
+ * <p>Note that in this case the fragment is not placed on the back stack, it
+ * is just added as an indefinitely running fragment. Because dialogs normally
+ * are modal, this will still operate as a back stack, since the dialog will
+ * capture user input until it is dismissed. When it is dismissed, DialogFragment
+ * will take care of removing itself from its fragment manager.
+ *
+ * <a name="DialogOrEmbed"></a>
+ * <h3>Selecting Between Dialog or Embedding</h3>
+ *
+ * <p>A DialogFragment can still optionally be used as a normal fragment, if
+ * desired. This is useful if you have a fragment that in some cases should
+ * be shown as a dialog and others embedded in a larger UI. This behavior
+ * will normally be automatically selected for you based on how you are using
+ * the fragment, but can be customized with {@link #setShowsDialog(boolean)}.
+ *
+ * <p>For example, here is a simple dialog fragment:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
+ * dialog}
+ *
+ * <p>An instance of this fragment can be created and shown as a dialog:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
+ * show_dialog}
+ *
+ * <p>It can also be added as content in a view hierarchy:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
+ * embed}
*/
public class DialogFragment extends Fragment
implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
@@ -70,11 +166,13 @@ public class DialogFragment extends Fragment
private static final String SAVED_STYLE = "android:style";
private static final String SAVED_THEME = "android:theme";
private static final String SAVED_CANCELABLE = "android:cancelable";
+ private static final String SAVED_SHOWS_DIALOG = "android:showsDialog";
private static final String SAVED_BACK_STACK_ID = "android:backStackId";
int mStyle = STYLE_NORMAL;
int mTheme = 0;
boolean mCancelable = true;
+ boolean mShowsDialog = true;
int mBackStackId = -1;
Dialog mDialog;
@@ -109,33 +207,42 @@ public class DialogFragment extends Fragment
}
/**
- * Display the dialog, adding the fragment to the given activity. This
+ * @deprecated Please use {@link #show(FragmentManager, String)}.
+ */
+ @Deprecated
+ public void show(Activity activity, String tag) {
+ FragmentTransaction ft = activity.openFragmentTransaction();
+ ft.add(this, tag);
+ ft.commit();
+ }
+
+ /**
+ * Display the dialog, adding the fragment to the given FragmentManager. This
* is a convenience for explicitly creating a transaction, adding the
* fragment to it with the given tag, and committing it. This does
* <em>not</em> add the transaction to the back stack. When the fragment
* is dismissed, a new transaction will be executed to remove it from
* the activity.
- * @param activity The activity this fragment will be added to.
+ * @param manager The FragmentManager this fragment will be added to.
* @param tag The tag for this fragment, as per
* {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
*/
- public void show(Activity activity, String tag) {
- FragmentTransaction ft = activity.openFragmentTransaction();
+ public void show(FragmentManager manager, String tag) {
+ FragmentTransaction ft = manager.openTransaction();
ft.add(this, tag);
ft.commit();
}
/**
- * Display the dialog, adding the fragment to the given activity using
- * an existing transaction and then committing the transaction.
- * @param activity The activity this fragment will be added to.
+ * Display the dialog, adding the fragment using an existing transaction
+ * and then committing the transaction.
* @param transaction An existing transaction in which to add the fragment.
* @param tag The tag for this fragment, as per
* {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
* @return Returns the identifier of the committed transaction, as per
* {@link FragmentTransaction#commit() FragmentTransaction.commit()}.
*/
- public int show(Activity activity, FragmentTransaction transaction, String tag) {
+ public int show(FragmentTransaction transaction, String tag) {
transaction.add(this, tag);
mRemoved = false;
mBackStackId = transaction.commit();
@@ -173,23 +280,67 @@ public class DialogFragment extends Fragment
return mTheme;
}
+ /**
+ * Control whether the shown Dialog is cancelable. Use this instead of
+ * directly calling {@link Dialog#setCancelable(boolean)
+ * Dialog.setCancelable(boolean)}, because DialogFragment needs to change
+ * its behavior based on this.
+ *
+ * @param cancelable If true, the dialog is cancelable. The default
+ * is true.
+ */
public void setCancelable(boolean cancelable) {
mCancelable = cancelable;
if (mDialog != null) mDialog.setCancelable(cancelable);
}
+ /**
+ * Return the current value of {@link #setCancelable(boolean)}.
+ */
public boolean getCancelable() {
return mCancelable;
}
+ /**
+ * Controls whether this fragment should be shown in a dialog. If not
+ * set, no Dialog will be created in {@link #onActivityCreated(Bundle)},
+ * and the fragment's view hierarchy will thus not be added to it. This
+ * allows you to instead use it as a normal fragment (embedded inside of
+ * its activity).
+ *
+ * <p>This is normally set for you based on whether the fragment is
+ * associated with a container view ID passed to
+ * {@link FragmentTransaction#add(int, Fragment) FragmentTransaction.add(int, Fragment)}.
+ * If the fragment was added with a container, setShowsDialog will be
+ * initialized to false; otherwise, it will be true.
+ *
+ * @param showsDialog If true, the fragment will be displayed in a Dialog.
+ * If false, no Dialog will be created and the fragment's view hierarchly
+ * left undisturbed.
+ */
+ public void setShowsDialog(boolean showsDialog) {
+ mShowsDialog = showsDialog;
+ }
+
+ /**
+ * Return the current value of {@link #setShowsDialog(boolean)}.
+ */
+ public boolean getShowsDialog() {
+ return mShowsDialog;
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ mShowsDialog = mContainerId == 0;
+
if (savedInstanceState != null) {
- mStyle = savedInstanceState.getInt(SAVED_STYLE, mStyle);
- mTheme = savedInstanceState.getInt(SAVED_THEME, mTheme);
- mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, mCancelable);
- mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, mBackStackId);
+ mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);
+ mTheme = savedInstanceState.getInt(SAVED_THEME, 0);
+ mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);
+ mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
+ mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);
}
}
@@ -209,6 +360,11 @@ public class DialogFragment extends Fragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+
+ if (!mShowsDialog) {
+ return;
+ }
+
mDialog = onCreateDialog(savedInstanceState);
mDestroyed = false;
switch (mStyle) {
@@ -258,10 +414,21 @@ public class DialogFragment extends Fragment
outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState);
}
}
- outState.putInt(SAVED_STYLE, mStyle);
- outState.putInt(SAVED_THEME, mTheme);
- outState.putBoolean(SAVED_CANCELABLE, mCancelable);
- outState.putInt(SAVED_BACK_STACK_ID, mBackStackId);
+ if (mStyle != STYLE_NORMAL) {
+ outState.putInt(SAVED_STYLE, mStyle);
+ }
+ if (mTheme != 0) {
+ outState.putInt(SAVED_THEME, mTheme);
+ }
+ if (!mCancelable) {
+ outState.putBoolean(SAVED_CANCELABLE, mCancelable);
+ }
+ if (!mShowsDialog) {
+ outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
+ }
+ if (mBackStackId != -1) {
+ outState.putInt(SAVED_BACK_STACK_ID, mBackStackId);
+ }
}
@Override
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index b10a8a8..56cf399 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -849,6 +849,25 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
mCalled = true;
}
+ /**
+ * Called to ask the fragment to save its current dynamic state, so it
+ * can later be reconstructed in a new instance of its process is
+ * restarted. If a new instance of the fragment later needs to be
+ * created, the data you place in the Bundle here will be available
+ * in the Bundle given to {@link #onCreate(Bundle)},
+ * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and
+ * {@link #onActivityCreated(Bundle)}.
+ *
+ * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle)
+ * Activity.onnSaveInstanceState(Bundle)} and most of the discussion there
+ * applies here as well. Note however: <em>this method may be called
+ * at any time before {@link #onDestroy()}</em>. There are many situations
+ * where a fragment may be mostly torn down (such as when placed on the
+ * back stack with no UI showing), but its state will not be saved until
+ * its owning activity actually needs to save its state.
+ *
+ * @param outState Bundle in which to place your saved state.
+ */
public void onSaveInstanceState(Bundle outState) {
}