diff options
| author | Dianne Hackborn <hackbod@google.com> | 2010-07-22 12:17:04 -0700 |
|---|---|---|
| committer | Dianne Hackborn <hackbod@google.com> | 2010-07-24 11:42:05 -0700 |
| commit | dd913a50cd72d6dd23c4ea437f0ebe2be05ca2e8 (patch) | |
| tree | 43981083af4f3bd25ec35b78d638e8a3a6d9a71a /core/java/android/app/DialogFragment.java | |
| parent | 3ad4a1b13f789757a46dc0aea98c97b9fdc5ef6c (diff) | |
Add new DialogFragment class.
For all your Dialog needs.
Change-Id: I36c602ca253488d34a55c8f0be610b9752c33264
Diffstat (limited to 'core/java/android/app/DialogFragment.java')
| -rw-r--r-- | core/java/android/app/DialogFragment.java | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java new file mode 100644 index 000000000000..391f67282329 --- /dev/null +++ b/core/java/android/app/DialogFragment.java @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +/** + * A fragment that displays a dialog window, floating on top of its + * activity's window. This fragment contains a Dialog object, which it + * displays as appropriate based on the fragment's state. Control of + * the dialog (deciding when to show, hide, dismiss it) should be done through + * the API here, not with direct calls on the dialog. + * + * <p>Implementations should override this class and implement + * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} to supply the + * 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. + */ +public class DialogFragment extends Fragment + implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { + + /** + * Style for {@link #DialogFragment(int, int)} constructor: a basic, + * normal dialog. + */ + public static final int STYLE_NORMAL = 0; + + /** + * Style for {@link #DialogFragment(int, int)} constructor: don't include + * a title area. + */ + public static final int STYLE_NO_TITLE = 1; + + /** + * Style for {@link #DialogFragment(int, int)} constructor: don't draw + * any frame at all; the view hierarchy returned by {@link #onCreateView} + * is entirely responsible for drawing the dialog. + */ + public static final int STYLE_NO_FRAME = 2; + + /** + * Style for {@link #DialogFragment(int, int)} constructor: like + * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog. + * The user can not touch it, and its window will not receive input focus. + */ + public static final int STYLE_NO_INPUT = 3; + + private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState"; + 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_BACK_STACK_ID = "android:backStackId"; + + int mStyle = STYLE_NORMAL; + int mTheme = 0; + boolean mCancelable = true; + int mBackStackId = -1; + + Dialog mDialog; + boolean mDestroyed; + + public DialogFragment() { + } + + /** + * Constructor to customize the basic appearance and behavior of the + * fragment's dialog. This can be used for some common dialog behaviors, + * taking care of selecting flags, theme, and other options for you. The + * same effect can be achieve by manually setting Dialog and Window + * attributes yourself. + * + * @param style Selects a standard style: may be {@link #STYLE_NORMAL}, + * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or + * {@link #STYLE_NO_INPUT}. + * @param theme Optional custom theme. If 0, an appropriate theme (based + * on the style) will be selected for you. + */ + public DialogFragment(int style, int theme) { + mStyle = style; + if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { + mTheme = android.R.style.Theme_Dialog_NoFrame; + } + if (theme != 0) { + mTheme = theme; + } + } + + /** + * Display the dialog, adding the fragment to the given activity. 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 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(); + 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. + * @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) { + transaction.add(this, tag); + mBackStackId = transaction.commit(); + return mBackStackId; + } + + /** + * Dismiss the fragment and its dialog. If the fragment was added to the + * back stack, all back stack state up to and including this entry will + * be popped. Otherwise, a new transaction will be committed to remove + * the fragment. + */ + public void dismiss() { + if (mDialog != null) { + mDialog.dismiss(); + } + if (mBackStackId >= 0) { + getActivity().popBackStack(mBackStackId, Activity.POP_BACK_STACK_INCLUSIVE); + mBackStackId = -1; + } else { + FragmentTransaction ft = getActivity().openFragmentTransaction(); + ft.remove(this); + ft.commit(); + } + } + + public Dialog getDialog() { + return mDialog; + } + + public int getTheme() { + return mTheme; + } + + public void setCancelable(boolean cancelable) { + mCancelable = cancelable; + if (mDialog != null) mDialog.setCancelable(cancelable); + } + + public boolean getCancelable() { + return mCancelable; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + 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); + } + } + + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new Dialog(getActivity(), getTheme()); + } + + public void onCancel(DialogInterface dialog) { + if (mBackStackId >= 0) { + // If this fragment is part of the back stack, then cancelling + // the dialog means popping off the back stack. + getActivity().popBackStack(mBackStackId, Activity.POP_BACK_STACK_INCLUSIVE); + mBackStackId = -1; + } + } + + public void onDismiss(DialogInterface dialog) { + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mDialog = onCreateDialog(savedInstanceState); + mDestroyed = false; + switch (mStyle) { + case STYLE_NO_INPUT: + mDialog.getWindow().addFlags( + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); + // fall through... + case STYLE_NO_FRAME: + case STYLE_NO_TITLE: + mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + } + View view = getView(); + if (view != null) { + if (view.getParent() != null) { + throw new IllegalStateException("DialogFragment can not be attached to a container view"); + } + mDialog.setContentView(view); + } + mDialog.setOwnerActivity(getActivity()); + mDialog.setCancelable(mCancelable); + mDialog.setOnCancelListener(this); + mDialog.setOnDismissListener(this); + if (savedInstanceState != null) { + Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG); + if (dialogState != null) { + mDialog.onRestoreInstanceState(dialogState); + } + } + } + + @Override + public void onStart() { + super.onStart(); + mDialog.show(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if (mDialog != null) { + Bundle dialogState = mDialog.onSaveInstanceState(); + if (dialogState != null) { + 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); + } + + @Override + public void onStop() { + super.onStop(); + mDialog.hide(); + } + + /** + * Detach from list view. + */ + @Override + public void onDestroyView() { + super.onDestroyView(); + mDestroyed = true; + mDialog.dismiss(); + mDialog = null; + } +} |
