diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-08-20 18:26:01 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-08-20 18:32:41 -0700 |
commit | 727782053ced0cac5beadc2c7ee9382d0f1ba1f5 (patch) | |
tree | 211c306b0f7a118a801813339f17f24bd96042de /core/java/android/app | |
parent | 76dd2ce960fea031887bf0a1a26d0ea761812f3e (diff) | |
download | frameworks_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.java | 199 | ||||
-rw-r--r-- | core/java/android/app/Fragment.java | 19 |
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) { } |