blob: e4c84d7e799713698c5abb0d9eaeb7848a698c95 [file] [log] [blame]
Dianne Hackborndd913a52010-07-22 12:17:04 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
Artur Satayevc895b1b2019-12-10 17:47:51 +000019import android.compat.annotation.UnsupportedAppUsage;
Dianne Hackborn7187ccb2011-01-24 23:58:13 -080020import android.content.Context;
Dianne Hackborndd913a52010-07-22 12:17:04 -070021import android.content.DialogInterface;
22import android.os.Bundle;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.view.ViewGroup;
26import android.view.Window;
27import android.view.WindowManager;
28
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -080029import java.io.FileDescriptor;
30import java.io.PrintWriter;
31
Dianne Hackborndd913a52010-07-22 12:17:04 -070032/**
33 * A fragment that displays a dialog window, floating on top of its
34 * activity's window. This fragment contains a Dialog object, which it
35 * displays as appropriate based on the fragment's state. Control of
36 * the dialog (deciding when to show, hide, dismiss it) should be done through
37 * the API here, not with direct calls on the dialog.
38 *
39 * <p>Implementations should override this class and implement
40 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} to supply the
41 * content of the dialog. Alternatively, they can override
42 * {@link #onCreateDialog(Bundle)} to create an entirely custom dialog, such
43 * as an AlertDialog, with its own content.
Dianne Hackborn72778202010-08-20 18:26:01 -070044 *
45 * <p>Topics covered here:
46 * <ol>
47 * <li><a href="#Lifecycle">Lifecycle</a>
48 * <li><a href="#BasicDialog">Basic Dialog</a>
49 * <li><a href="#AlertDialog">Alert Dialog</a>
50 * <li><a href="#DialogOrEmbed">Selecting Between Dialog or Embedding</a>
51 * </ol>
52 *
53 * <a name="Lifecycle"></a>
54 * <h3>Lifecycle</h3>
55 *
56 * <p>DialogFragment does various things to keep the fragment's lifecycle
57 * driving it, instead of the Dialog. Note that dialogs are generally
58 * autonomous entities -- they are their own window, receiving their own
59 * input events, and often deciding on their own when to disappear (by
60 * receiving a back key event or the user clicking on a button).
61 *
62 * <p>DialogFragment needs to ensure that what is happening with the Fragment
63 * and Dialog states remains consistent. To do this, it watches for dismiss
Scott Mainfd516982012-07-03 16:25:52 -070064 * events from the dialog and takes care of removing its own state when they
Dianne Hackborn72778202010-08-20 18:26:01 -070065 * happen. This means you should use {@link #show(FragmentManager, String)}
66 * or {@link #show(FragmentTransaction, String)} to add an instance of
67 * DialogFragment to your UI, as these keep track of how DialogFragment should
68 * remove itself when the dialog is dismissed.
69 *
70 * <a name="BasicDialog"></a>
71 * <h3>Basic Dialog</h3>
72 *
73 * <p>The simplest use of DialogFragment is as a floating container for the
74 * fragment's view hierarchy. A simple implementation may look like this:
75 *
76 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialog.java
77 * dialog}
78 *
79 * <p>An example showDialog() method on the Activity could be:
80 *
81 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialog.java
82 * add_dialog}
83 *
84 * <p>This removes any currently shown dialog, creates a new DialogFragment
85 * with an argument, and shows it as a new state on the back stack. When the
86 * transaction is popped, the current DialogFragment and its Dialog will be
87 * destroyed, and the previous one (if any) re-shown. Note that in this case
88 * DialogFragment will take care of popping the transaction of the Dialog
89 * is dismissed separately from it.
90 *
91 * <a name="AlertDialog"></a>
92 * <h3>Alert Dialog</h3>
93 *
94 * <p>Instead of (or in addition to) implementing {@link #onCreateView} to
95 * generate the view hierarchy inside of a dialog, you may implement
96 * {@link #onCreateDialog(Bundle)} to create your own custom Dialog object.
97 *
98 * <p>This is most useful for creating an {@link AlertDialog}, allowing you
99 * to display standard alerts to the user that are managed by a fragment.
100 * A simple example implementation of this is:
101 *
102 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.java
103 * dialog}
104 *
105 * <p>The activity creating this fragment may have the following methods to
106 * show the dialog and receive results from it:
107 *
108 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.java
109 * activity}
110 *
111 * <p>Note that in this case the fragment is not placed on the back stack, it
112 * is just added as an indefinitely running fragment. Because dialogs normally
113 * are modal, this will still operate as a back stack, since the dialog will
114 * capture user input until it is dismissed. When it is dismissed, DialogFragment
115 * will take care of removing itself from its fragment manager.
116 *
117 * <a name="DialogOrEmbed"></a>
118 * <h3>Selecting Between Dialog or Embedding</h3>
119 *
120 * <p>A DialogFragment can still optionally be used as a normal fragment, if
121 * desired. This is useful if you have a fragment that in some cases should
122 * be shown as a dialog and others embedded in a larger UI. This behavior
123 * will normally be automatically selected for you based on how you are using
124 * the fragment, but can be customized with {@link #setShowsDialog(boolean)}.
125 *
126 * <p>For example, here is a simple dialog fragment:
127 *
128 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
129 * dialog}
130 *
131 * <p>An instance of this fragment can be created and shown as a dialog:
132 *
133 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
134 * show_dialog}
135 *
136 * <p>It can also be added as content in a view hierarchy:
137 *
138 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
139 * embed}
Ian Lake0a1feb82017-11-13 10:26:46 -0800140 *
Ian Lake1f4e67b2017-12-18 10:36:18 -0800141 * @deprecated Use the <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>
142 * {@link android.support.v4.app.DialogFragment} for consistent behavior across all devices
143 * and access to <a href="{@docRoot}topic/libraries/architecture/lifecycle.html">Lifecycle</a>.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700144 */
Ian Lake0a1feb82017-11-13 10:26:46 -0800145@Deprecated
Dianne Hackborndd913a52010-07-22 12:17:04 -0700146public class DialogFragment extends Fragment
147 implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
148
149 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700150 * Style for {@link #setStyle(int, int)}: a basic,
Dianne Hackborndd913a52010-07-22 12:17:04 -0700151 * normal dialog.
152 */
153 public static final int STYLE_NORMAL = 0;
154
155 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700156 * Style for {@link #setStyle(int, int)}: don't include
Dianne Hackborndd913a52010-07-22 12:17:04 -0700157 * a title area.
158 */
159 public static final int STYLE_NO_TITLE = 1;
160
161 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700162 * Style for {@link #setStyle(int, int)}: don't draw
Dianne Hackborndd913a52010-07-22 12:17:04 -0700163 * any frame at all; the view hierarchy returned by {@link #onCreateView}
164 * is entirely responsible for drawing the dialog.
165 */
166 public static final int STYLE_NO_FRAME = 2;
167
168 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700169 * Style for {@link #setStyle(int, int)}: like
Dianne Hackborndd913a52010-07-22 12:17:04 -0700170 * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog.
171 * The user can not touch it, and its window will not receive input focus.
172 */
173 public static final int STYLE_NO_INPUT = 3;
174
175 private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState";
176 private static final String SAVED_STYLE = "android:style";
177 private static final String SAVED_THEME = "android:theme";
178 private static final String SAVED_CANCELABLE = "android:cancelable";
Dianne Hackborn72778202010-08-20 18:26:01 -0700179 private static final String SAVED_SHOWS_DIALOG = "android:showsDialog";
Dianne Hackborndd913a52010-07-22 12:17:04 -0700180 private static final String SAVED_BACK_STACK_ID = "android:backStackId";
181
182 int mStyle = STYLE_NORMAL;
183 int mTheme = 0;
184 boolean mCancelable = true;
Dianne Hackborn72778202010-08-20 18:26:01 -0700185 boolean mShowsDialog = true;
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100186 @UnsupportedAppUsage
Dianne Hackborndd913a52010-07-22 12:17:04 -0700187 int mBackStackId = -1;
188
189 Dialog mDialog;
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100190 @UnsupportedAppUsage
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800191 boolean mViewDestroyed;
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100192 @UnsupportedAppUsage
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800193 boolean mDismissed;
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100194 @UnsupportedAppUsage
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800195 boolean mShownByMe;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700196
197 public DialogFragment() {
198 }
199
200 /**
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700201 * Call to customize the basic appearance and behavior of the
Dianne Hackborndd913a52010-07-22 12:17:04 -0700202 * fragment's dialog. This can be used for some common dialog behaviors,
203 * taking care of selecting flags, theme, and other options for you. The
204 * same effect can be achieve by manually setting Dialog and Window
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700205 * attributes yourself. Calling this after the fragment's Dialog is
206 * created will have no effect.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700207 *
208 * @param style Selects a standard style: may be {@link #STYLE_NORMAL},
209 * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or
210 * {@link #STYLE_NO_INPUT}.
211 * @param theme Optional custom theme. If 0, an appropriate theme (based
212 * on the style) will be selected for you.
213 */
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700214 public void setStyle(int style, int theme) {
Dianne Hackborndd913a52010-07-22 12:17:04 -0700215 mStyle = style;
216 if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
Adam Powell6e90a362011-08-14 16:48:32 -0700217 mTheme = com.android.internal.R.style.Theme_DeviceDefault_Dialog_NoFrame;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700218 }
219 if (theme != 0) {
220 mTheme = theme;
221 }
222 }
223
224 /**
Dianne Hackborn72778202010-08-20 18:26:01 -0700225 * Display the dialog, adding the fragment to the given FragmentManager. This
226 * is a convenience for explicitly creating a transaction, adding the
227 * fragment to it with the given tag, and committing it. This does
228 * <em>not</em> add the transaction to the back stack. When the fragment
229 * is dismissed, a new transaction will be executed to remove it from
230 * the activity.
231 * @param manager The FragmentManager this fragment will be added to.
232 * @param tag The tag for this fragment, as per
233 * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
234 */
235 public void show(FragmentManager manager, String tag) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800236 mDismissed = false;
237 mShownByMe = true;
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800238 FragmentTransaction ft = manager.beginTransaction();
Dianne Hackborn72778202010-08-20 18:26:01 -0700239 ft.add(this, tag);
240 ft.commit();
241 }
242
Jeff Sharkey063f8502015-08-13 16:57:29 -0700243 /** {@hide} */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100244 @UnsupportedAppUsage
Jeff Sharkey063f8502015-08-13 16:57:29 -0700245 public void showAllowingStateLoss(FragmentManager manager, String tag) {
246 mDismissed = false;
247 mShownByMe = true;
248 FragmentTransaction ft = manager.beginTransaction();
249 ft.add(this, tag);
250 ft.commitAllowingStateLoss();
251 }
252
Dianne Hackborn72778202010-08-20 18:26:01 -0700253 /**
254 * Display the dialog, adding the fragment using an existing transaction
255 * and then committing the transaction.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700256 * @param transaction An existing transaction in which to add the fragment.
257 * @param tag The tag for this fragment, as per
258 * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
259 * @return Returns the identifier of the committed transaction, as per
260 * {@link FragmentTransaction#commit() FragmentTransaction.commit()}.
261 */
Dianne Hackborn72778202010-08-20 18:26:01 -0700262 public int show(FragmentTransaction transaction, String tag) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800263 mDismissed = false;
264 mShownByMe = true;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700265 transaction.add(this, tag);
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800266 mViewDestroyed = false;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700267 mBackStackId = transaction.commit();
268 return mBackStackId;
269 }
270
271 /**
272 * Dismiss the fragment and its dialog. If the fragment was added to the
273 * back stack, all back stack state up to and including this entry will
274 * be popped. Otherwise, a new transaction will be committed to remove
275 * the fragment.
276 */
277 public void dismiss() {
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700278 dismissInternal(false);
279 }
280
Dianne Hackborncf407ad2011-03-11 13:17:57 -0800281 /**
282 * Version of {@link #dismiss()} that uses
283 * {@link FragmentTransaction#commitAllowingStateLoss()
284 * FragmentTransaction.commitAllowingStateLoss()}. See linked
285 * documentation for further details.
286 */
287 public void dismissAllowingStateLoss() {
288 dismissInternal(true);
289 }
290
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700291 void dismissInternal(boolean allowStateLoss) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800292 if (mDismissed) {
293 return;
294 }
295 mDismissed = true;
296 mShownByMe = false;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700297 if (mDialog != null) {
298 mDialog.dismiss();
Dianne Hackborndef15372010-08-15 12:43:52 -0700299 mDialog = null;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700300 }
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800301 mViewDestroyed = true;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700302 if (mBackStackId >= 0) {
Dianne Hackborndef15372010-08-15 12:43:52 -0700303 getFragmentManager().popBackStack(mBackStackId,
304 FragmentManager.POP_BACK_STACK_INCLUSIVE);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700305 mBackStackId = -1;
306 } else {
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800307 FragmentTransaction ft = getFragmentManager().beginTransaction();
Dianne Hackborndd913a52010-07-22 12:17:04 -0700308 ft.remove(this);
Dianne Hackborn6908cd12010-11-08 15:11:16 -0800309 if (allowStateLoss) {
310 ft.commitAllowingStateLoss();
311 } else {
312 ft.commit();
313 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700314 }
315 }
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700316
Dianne Hackborndd913a52010-07-22 12:17:04 -0700317 public Dialog getDialog() {
318 return mDialog;
319 }
320
321 public int getTheme() {
322 return mTheme;
323 }
324
Dianne Hackborn72778202010-08-20 18:26:01 -0700325 /**
326 * Control whether the shown Dialog is cancelable. Use this instead of
327 * directly calling {@link Dialog#setCancelable(boolean)
328 * Dialog.setCancelable(boolean)}, because DialogFragment needs to change
329 * its behavior based on this.
330 *
331 * @param cancelable If true, the dialog is cancelable. The default
332 * is true.
333 */
Dianne Hackborndd913a52010-07-22 12:17:04 -0700334 public void setCancelable(boolean cancelable) {
335 mCancelable = cancelable;
336 if (mDialog != null) mDialog.setCancelable(cancelable);
337 }
338
Dianne Hackborn72778202010-08-20 18:26:01 -0700339 /**
340 * Return the current value of {@link #setCancelable(boolean)}.
341 */
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800342 public boolean isCancelable() {
Dianne Hackborndd913a52010-07-22 12:17:04 -0700343 return mCancelable;
344 }
345
Dianne Hackborn72778202010-08-20 18:26:01 -0700346 /**
347 * Controls whether this fragment should be shown in a dialog. If not
348 * set, no Dialog will be created in {@link #onActivityCreated(Bundle)},
349 * and the fragment's view hierarchy will thus not be added to it. This
350 * allows you to instead use it as a normal fragment (embedded inside of
351 * its activity).
352 *
353 * <p>This is normally set for you based on whether the fragment is
354 * associated with a container view ID passed to
355 * {@link FragmentTransaction#add(int, Fragment) FragmentTransaction.add(int, Fragment)}.
356 * If the fragment was added with a container, setShowsDialog will be
357 * initialized to false; otherwise, it will be true.
358 *
359 * @param showsDialog If true, the fragment will be displayed in a Dialog.
360 * If false, no Dialog will be created and the fragment's view hierarchly
361 * left undisturbed.
362 */
363 public void setShowsDialog(boolean showsDialog) {
364 mShowsDialog = showsDialog;
365 }
366
367 /**
368 * Return the current value of {@link #setShowsDialog(boolean)}.
369 */
370 public boolean getShowsDialog() {
371 return mShowsDialog;
372 }
373
Dianne Hackborndd913a52010-07-22 12:17:04 -0700374 @Override
Adam Powell31479e32016-04-22 11:27:31 -0700375 public void onAttach(Context context) {
376 super.onAttach(context);
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800377 if (!mShownByMe) {
378 // If not explicitly shown through our API, take this as an
379 // indication that the dialog is no longer dismissed.
380 mDismissed = false;
381 }
382 }
383
384 @Override
385 public void onDetach() {
386 super.onDetach();
387 if (!mShownByMe && !mDismissed) {
388 // The fragment was not shown by a direct call here, it is not
389 // dismissed, and now it is being detached... well, okay, thou
390 // art now dismissed. Have fun.
391 mDismissed = true;
392 }
393 }
394
395 @Override
Dianne Hackborndd913a52010-07-22 12:17:04 -0700396 public void onCreate(Bundle savedInstanceState) {
397 super.onCreate(savedInstanceState);
Dianne Hackborn72778202010-08-20 18:26:01 -0700398
399 mShowsDialog = mContainerId == 0;
400
Dianne Hackborndd913a52010-07-22 12:17:04 -0700401 if (savedInstanceState != null) {
Dianne Hackborn72778202010-08-20 18:26:01 -0700402 mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);
403 mTheme = savedInstanceState.getInt(SAVED_THEME, 0);
404 mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);
405 mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
406 mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700407 }
408 }
409
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800410 /** @hide */
411 @Override
George Mountc7146be2017-03-29 14:13:03 +0000412 public LayoutInflater onGetLayoutInflater(Bundle savedInstanceState) {
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800413 if (!mShowsDialog) {
George Mountc7146be2017-03-29 14:13:03 +0000414 return super.onGetLayoutInflater(savedInstanceState);
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800415 }
416
417 mDialog = onCreateDialog(savedInstanceState);
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800418 switch (mStyle) {
419 case STYLE_NO_INPUT:
420 mDialog.getWindow().addFlags(
421 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
422 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
423 // fall through...
424 case STYLE_NO_FRAME:
425 case STYLE_NO_TITLE:
426 mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
427 }
Dianne Hackborn25193d32011-03-01 15:01:30 -0800428 if (mDialog != null) {
429 return (LayoutInflater)mDialog.getContext().getSystemService(
430 Context.LAYOUT_INFLATER_SERVICE);
431 }
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700432 return (LayoutInflater) mHost.getContext().getSystemService(
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800433 Context.LAYOUT_INFLATER_SERVICE);
434 }
435
436 /**
437 * Override to build your own custom Dialog container. This is typically
438 * used to show an AlertDialog instead of a generic Dialog; when doing so,
439 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} does not need
440 * to be implemented since the AlertDialog takes care of its own content.
441 *
442 * <p>This method will be called after {@link #onCreate(Bundle)} and
443 * before {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. The
444 * default implementation simply instantiates and returns a {@link Dialog}
445 * class.
446 *
Dianne Hackbornf812fee2011-01-25 14:54:29 -0800447 * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener
448 * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener
449 * Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em>
450 * To find out about these events, override {@link #onCancel(DialogInterface)}
451 * and {@link #onDismiss(DialogInterface)}.</p>
452 *
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800453 * @param savedInstanceState The last saved instance state of the Fragment,
454 * or null if this is a freshly created Fragment.
455 *
456 * @return Return a new Dialog instance to be displayed by the Fragment.
457 */
Dianne Hackborndd913a52010-07-22 12:17:04 -0700458 public Dialog onCreateDialog(Bundle savedInstanceState) {
459 return new Dialog(getActivity(), getTheme());
460 }
461
462 public void onCancel(DialogInterface dialog) {
Dianne Hackborndd913a52010-07-22 12:17:04 -0700463 }
464
465 public void onDismiss(DialogInterface dialog) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800466 if (!mViewDestroyed) {
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700467 // Note: we need to use allowStateLoss, because the dialog
468 // dispatches this asynchronously so we can receive the call
469 // after the activity is paused. Worst case, when the user comes
470 // back to the activity they see the dialog again.
471 dismissInternal(true);
Dianne Hackborndef15372010-08-15 12:43:52 -0700472 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700473 }
474
475 @Override
476 public void onActivityCreated(Bundle savedInstanceState) {
477 super.onActivityCreated(savedInstanceState);
Dianne Hackborn72778202010-08-20 18:26:01 -0700478
479 if (!mShowsDialog) {
480 return;
481 }
482
Dianne Hackborndd913a52010-07-22 12:17:04 -0700483 View view = getView();
484 if (view != null) {
485 if (view.getParent() != null) {
Adam Powell31479e32016-04-22 11:27:31 -0700486 throw new IllegalStateException(
487 "DialogFragment can not be attached to a container view");
Dianne Hackborndd913a52010-07-22 12:17:04 -0700488 }
489 mDialog.setContentView(view);
490 }
Adam Powell31479e32016-04-22 11:27:31 -0700491 final Activity activity = getActivity();
492 if (activity != null) {
493 mDialog.setOwnerActivity(activity);
494 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700495 mDialog.setCancelable(mCancelable);
Dianne Hackbornf812fee2011-01-25 14:54:29 -0800496 if (!mDialog.takeCancelAndDismissListeners("DialogFragment", this, this)) {
497 throw new IllegalStateException(
498 "You can not set Dialog's OnCancelListener or OnDismissListener");
499 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700500 if (savedInstanceState != null) {
501 Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG);
502 if (dialogState != null) {
503 mDialog.onRestoreInstanceState(dialogState);
504 }
505 }
506 }
507
508 @Override
509 public void onStart() {
510 super.onStart();
Dianne Hackborndef15372010-08-15 12:43:52 -0700511 if (mDialog != null) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800512 mViewDestroyed = false;
Dianne Hackborndef15372010-08-15 12:43:52 -0700513 mDialog.show();
514 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700515 }
516
517 @Override
518 public void onSaveInstanceState(Bundle outState) {
519 super.onSaveInstanceState(outState);
520 if (mDialog != null) {
521 Bundle dialogState = mDialog.onSaveInstanceState();
522 if (dialogState != null) {
523 outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState);
524 }
525 }
Dianne Hackborn72778202010-08-20 18:26:01 -0700526 if (mStyle != STYLE_NORMAL) {
527 outState.putInt(SAVED_STYLE, mStyle);
528 }
529 if (mTheme != 0) {
530 outState.putInt(SAVED_THEME, mTheme);
531 }
532 if (!mCancelable) {
533 outState.putBoolean(SAVED_CANCELABLE, mCancelable);
534 }
535 if (!mShowsDialog) {
536 outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
537 }
538 if (mBackStackId != -1) {
539 outState.putInt(SAVED_BACK_STACK_ID, mBackStackId);
540 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700541 }
542
543 @Override
544 public void onStop() {
545 super.onStop();
Dianne Hackborndef15372010-08-15 12:43:52 -0700546 if (mDialog != null) {
547 mDialog.hide();
548 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700549 }
550
551 /**
Dianne Hackborndef15372010-08-15 12:43:52 -0700552 * Remove dialog.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700553 */
554 @Override
555 public void onDestroyView() {
556 super.onDestroyView();
Dianne Hackborndef15372010-08-15 12:43:52 -0700557 if (mDialog != null) {
558 // Set removed here because this dismissal is just to hide
559 // the dialog -- we don't want this to cause the fragment to
560 // actually be removed.
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800561 mViewDestroyed = true;
Dianne Hackborndef15372010-08-15 12:43:52 -0700562 mDialog.dismiss();
563 mDialog = null;
564 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700565 }
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800566
567 @Override
568 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
569 super.dump(prefix, fd, writer, args);
570 writer.print(prefix); writer.println("DialogFragment:");
571 writer.print(prefix); writer.print(" mStyle="); writer.print(mStyle);
572 writer.print(" mTheme=0x"); writer.println(Integer.toHexString(mTheme));
573 writer.print(prefix); writer.print(" mCancelable="); writer.print(mCancelable);
574 writer.print(" mShowsDialog="); writer.print(mShowsDialog);
575 writer.print(" mBackStackId="); writer.println(mBackStackId);
576 writer.print(prefix); writer.print(" mDialog="); writer.println(mDialog);
577 writer.print(prefix); writer.print(" mViewDestroyed="); writer.print(mViewDestroyed);
578 writer.print(" mDismissed="); writer.print(mDismissed);
579 writer.print(" mShownByMe="); writer.println(mShownByMe);
580 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700581}