blob: 3198c7c086d1a355c995c089f8b33616edd1d723 [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
Dianne Hackborn7187ccb2011-01-24 23:58:13 -080019import android.content.Context;
Dianne Hackborndd913a52010-07-22 12:17:04 -070020import android.content.DialogInterface;
21import android.os.Bundle;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25import android.view.Window;
26import android.view.WindowManager;
27
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -080028import java.io.FileDescriptor;
29import java.io.PrintWriter;
30
Dianne Hackborndd913a52010-07-22 12:17:04 -070031/**
32 * A fragment that displays a dialog window, floating on top of its
33 * activity's window. This fragment contains a Dialog object, which it
34 * displays as appropriate based on the fragment's state. Control of
35 * the dialog (deciding when to show, hide, dismiss it) should be done through
36 * the API here, not with direct calls on the dialog.
37 *
38 * <p>Implementations should override this class and implement
39 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} to supply the
40 * content of the dialog. Alternatively, they can override
41 * {@link #onCreateDialog(Bundle)} to create an entirely custom dialog, such
42 * as an AlertDialog, with its own content.
Dianne Hackborn72778202010-08-20 18:26:01 -070043 *
44 * <p>Topics covered here:
45 * <ol>
46 * <li><a href="#Lifecycle">Lifecycle</a>
47 * <li><a href="#BasicDialog">Basic Dialog</a>
48 * <li><a href="#AlertDialog">Alert Dialog</a>
49 * <li><a href="#DialogOrEmbed">Selecting Between Dialog or Embedding</a>
50 * </ol>
51 *
52 * <a name="Lifecycle"></a>
53 * <h3>Lifecycle</h3>
54 *
55 * <p>DialogFragment does various things to keep the fragment's lifecycle
56 * driving it, instead of the Dialog. Note that dialogs are generally
57 * autonomous entities -- they are their own window, receiving their own
58 * input events, and often deciding on their own when to disappear (by
59 * receiving a back key event or the user clicking on a button).
60 *
61 * <p>DialogFragment needs to ensure that what is happening with the Fragment
62 * and Dialog states remains consistent. To do this, it watches for dismiss
Scott Mainfd516982012-07-03 16:25:52 -070063 * events from the dialog and takes care of removing its own state when they
Dianne Hackborn72778202010-08-20 18:26:01 -070064 * happen. This means you should use {@link #show(FragmentManager, String)}
65 * or {@link #show(FragmentTransaction, String)} to add an instance of
66 * DialogFragment to your UI, as these keep track of how DialogFragment should
67 * remove itself when the dialog is dismissed.
68 *
69 * <a name="BasicDialog"></a>
70 * <h3>Basic Dialog</h3>
71 *
72 * <p>The simplest use of DialogFragment is as a floating container for the
73 * fragment's view hierarchy. A simple implementation may look like this:
74 *
75 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialog.java
76 * dialog}
77 *
78 * <p>An example showDialog() method on the Activity could be:
79 *
80 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialog.java
81 * add_dialog}
82 *
83 * <p>This removes any currently shown dialog, creates a new DialogFragment
84 * with an argument, and shows it as a new state on the back stack. When the
85 * transaction is popped, the current DialogFragment and its Dialog will be
86 * destroyed, and the previous one (if any) re-shown. Note that in this case
87 * DialogFragment will take care of popping the transaction of the Dialog
88 * is dismissed separately from it.
89 *
90 * <a name="AlertDialog"></a>
91 * <h3>Alert Dialog</h3>
92 *
93 * <p>Instead of (or in addition to) implementing {@link #onCreateView} to
94 * generate the view hierarchy inside of a dialog, you may implement
95 * {@link #onCreateDialog(Bundle)} to create your own custom Dialog object.
96 *
97 * <p>This is most useful for creating an {@link AlertDialog}, allowing you
98 * to display standard alerts to the user that are managed by a fragment.
99 * A simple example implementation of this is:
100 *
101 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.java
102 * dialog}
103 *
104 * <p>The activity creating this fragment may have the following methods to
105 * show the dialog and receive results from it:
106 *
107 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialog.java
108 * activity}
109 *
110 * <p>Note that in this case the fragment is not placed on the back stack, it
111 * is just added as an indefinitely running fragment. Because dialogs normally
112 * are modal, this will still operate as a back stack, since the dialog will
113 * capture user input until it is dismissed. When it is dismissed, DialogFragment
114 * will take care of removing itself from its fragment manager.
115 *
116 * <a name="DialogOrEmbed"></a>
117 * <h3>Selecting Between Dialog or Embedding</h3>
118 *
119 * <p>A DialogFragment can still optionally be used as a normal fragment, if
120 * desired. This is useful if you have a fragment that in some cases should
121 * be shown as a dialog and others embedded in a larger UI. This behavior
122 * will normally be automatically selected for you based on how you are using
123 * the fragment, but can be customized with {@link #setShowsDialog(boolean)}.
124 *
125 * <p>For example, here is a simple dialog fragment:
126 *
127 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
128 * dialog}
129 *
130 * <p>An instance of this fragment can be created and shown as a dialog:
131 *
132 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
133 * show_dialog}
134 *
135 * <p>It can also be added as content in a view hierarchy:
136 *
137 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivity.java
138 * embed}
Dianne Hackborndd913a52010-07-22 12:17:04 -0700139 */
140public class DialogFragment extends Fragment
141 implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
142
143 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700144 * Style for {@link #setStyle(int, int)}: a basic,
Dianne Hackborndd913a52010-07-22 12:17:04 -0700145 * normal dialog.
146 */
147 public static final int STYLE_NORMAL = 0;
148
149 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700150 * Style for {@link #setStyle(int, int)}: don't include
Dianne Hackborndd913a52010-07-22 12:17:04 -0700151 * a title area.
152 */
153 public static final int STYLE_NO_TITLE = 1;
154
155 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700156 * Style for {@link #setStyle(int, int)}: don't draw
Dianne Hackborndd913a52010-07-22 12:17:04 -0700157 * any frame at all; the view hierarchy returned by {@link #onCreateView}
158 * is entirely responsible for drawing the dialog.
159 */
160 public static final int STYLE_NO_FRAME = 2;
161
162 /**
Jean-Baptiste Queru72dc7802010-08-13 09:25:19 -0700163 * Style for {@link #setStyle(int, int)}: like
Dianne Hackborndd913a52010-07-22 12:17:04 -0700164 * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog.
165 * The user can not touch it, and its window will not receive input focus.
166 */
167 public static final int STYLE_NO_INPUT = 3;
168
169 private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState";
170 private static final String SAVED_STYLE = "android:style";
171 private static final String SAVED_THEME = "android:theme";
172 private static final String SAVED_CANCELABLE = "android:cancelable";
Dianne Hackborn72778202010-08-20 18:26:01 -0700173 private static final String SAVED_SHOWS_DIALOG = "android:showsDialog";
Dianne Hackborndd913a52010-07-22 12:17:04 -0700174 private static final String SAVED_BACK_STACK_ID = "android:backStackId";
175
176 int mStyle = STYLE_NORMAL;
177 int mTheme = 0;
178 boolean mCancelable = true;
Dianne Hackborn72778202010-08-20 18:26:01 -0700179 boolean mShowsDialog = true;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700180 int mBackStackId = -1;
181
182 Dialog mDialog;
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800183 boolean mViewDestroyed;
184 boolean mDismissed;
185 boolean mShownByMe;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700186
187 public DialogFragment() {
188 }
189
190 /**
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700191 * Call to customize the basic appearance and behavior of the
Dianne Hackborndd913a52010-07-22 12:17:04 -0700192 * fragment's dialog. This can be used for some common dialog behaviors,
193 * taking care of selecting flags, theme, and other options for you. The
194 * same effect can be achieve by manually setting Dialog and Window
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700195 * attributes yourself. Calling this after the fragment's Dialog is
196 * created will have no effect.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700197 *
198 * @param style Selects a standard style: may be {@link #STYLE_NORMAL},
199 * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or
200 * {@link #STYLE_NO_INPUT}.
201 * @param theme Optional custom theme. If 0, an appropriate theme (based
202 * on the style) will be selected for you.
203 */
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700204 public void setStyle(int style, int theme) {
Dianne Hackborndd913a52010-07-22 12:17:04 -0700205 mStyle = style;
206 if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
Adam Powell6e90a362011-08-14 16:48:32 -0700207 mTheme = com.android.internal.R.style.Theme_DeviceDefault_Dialog_NoFrame;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700208 }
209 if (theme != 0) {
210 mTheme = theme;
211 }
212 }
213
214 /**
Dianne Hackborn72778202010-08-20 18:26:01 -0700215 * Display the dialog, adding the fragment to the given FragmentManager. This
216 * is a convenience for explicitly creating a transaction, adding the
217 * fragment to it with the given tag, and committing it. This does
218 * <em>not</em> add the transaction to the back stack. When the fragment
219 * is dismissed, a new transaction will be executed to remove it from
220 * the activity.
221 * @param manager The FragmentManager this fragment will be added to.
222 * @param tag The tag for this fragment, as per
223 * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
224 */
225 public void show(FragmentManager manager, String tag) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800226 mDismissed = false;
227 mShownByMe = true;
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800228 FragmentTransaction ft = manager.beginTransaction();
Dianne Hackborn72778202010-08-20 18:26:01 -0700229 ft.add(this, tag);
230 ft.commit();
231 }
232
Jeff Sharkey063f8502015-08-13 16:57:29 -0700233 /** {@hide} */
234 public void showAllowingStateLoss(FragmentManager manager, String tag) {
235 mDismissed = false;
236 mShownByMe = true;
237 FragmentTransaction ft = manager.beginTransaction();
238 ft.add(this, tag);
239 ft.commitAllowingStateLoss();
240 }
241
Dianne Hackborn72778202010-08-20 18:26:01 -0700242 /**
243 * Display the dialog, adding the fragment using an existing transaction
244 * and then committing the transaction.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700245 * @param transaction An existing transaction in which to add the fragment.
246 * @param tag The tag for this fragment, as per
247 * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
248 * @return Returns the identifier of the committed transaction, as per
249 * {@link FragmentTransaction#commit() FragmentTransaction.commit()}.
250 */
Dianne Hackborn72778202010-08-20 18:26:01 -0700251 public int show(FragmentTransaction transaction, String tag) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800252 mDismissed = false;
253 mShownByMe = true;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700254 transaction.add(this, tag);
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800255 mViewDestroyed = false;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700256 mBackStackId = transaction.commit();
257 return mBackStackId;
258 }
259
260 /**
261 * Dismiss the fragment and its dialog. If the fragment was added to the
262 * back stack, all back stack state up to and including this entry will
263 * be popped. Otherwise, a new transaction will be committed to remove
264 * the fragment.
265 */
266 public void dismiss() {
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700267 dismissInternal(false);
268 }
269
Dianne Hackborncf407ad2011-03-11 13:17:57 -0800270 /**
271 * Version of {@link #dismiss()} that uses
272 * {@link FragmentTransaction#commitAllowingStateLoss()
273 * FragmentTransaction.commitAllowingStateLoss()}. See linked
274 * documentation for further details.
275 */
276 public void dismissAllowingStateLoss() {
277 dismissInternal(true);
278 }
279
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700280 void dismissInternal(boolean allowStateLoss) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800281 if (mDismissed) {
282 return;
283 }
284 mDismissed = true;
285 mShownByMe = false;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700286 if (mDialog != null) {
287 mDialog.dismiss();
Dianne Hackborndef15372010-08-15 12:43:52 -0700288 mDialog = null;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700289 }
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800290 mViewDestroyed = true;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700291 if (mBackStackId >= 0) {
Dianne Hackborndef15372010-08-15 12:43:52 -0700292 getFragmentManager().popBackStack(mBackStackId,
293 FragmentManager.POP_BACK_STACK_INCLUSIVE);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700294 mBackStackId = -1;
295 } else {
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800296 FragmentTransaction ft = getFragmentManager().beginTransaction();
Dianne Hackborndd913a52010-07-22 12:17:04 -0700297 ft.remove(this);
Dianne Hackborn6908cd12010-11-08 15:11:16 -0800298 if (allowStateLoss) {
299 ft.commitAllowingStateLoss();
300 } else {
301 ft.commit();
302 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700303 }
304 }
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700305
Dianne Hackborndd913a52010-07-22 12:17:04 -0700306 public Dialog getDialog() {
307 return mDialog;
308 }
309
310 public int getTheme() {
311 return mTheme;
312 }
313
Dianne Hackborn72778202010-08-20 18:26:01 -0700314 /**
315 * Control whether the shown Dialog is cancelable. Use this instead of
316 * directly calling {@link Dialog#setCancelable(boolean)
317 * Dialog.setCancelable(boolean)}, because DialogFragment needs to change
318 * its behavior based on this.
319 *
320 * @param cancelable If true, the dialog is cancelable. The default
321 * is true.
322 */
Dianne Hackborndd913a52010-07-22 12:17:04 -0700323 public void setCancelable(boolean cancelable) {
324 mCancelable = cancelable;
325 if (mDialog != null) mDialog.setCancelable(cancelable);
326 }
327
Dianne Hackborn72778202010-08-20 18:26:01 -0700328 /**
329 * Return the current value of {@link #setCancelable(boolean)}.
330 */
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800331 public boolean isCancelable() {
Dianne Hackborndd913a52010-07-22 12:17:04 -0700332 return mCancelable;
333 }
334
Dianne Hackborn72778202010-08-20 18:26:01 -0700335 /**
336 * Controls whether this fragment should be shown in a dialog. If not
337 * set, no Dialog will be created in {@link #onActivityCreated(Bundle)},
338 * and the fragment's view hierarchy will thus not be added to it. This
339 * allows you to instead use it as a normal fragment (embedded inside of
340 * its activity).
341 *
342 * <p>This is normally set for you based on whether the fragment is
343 * associated with a container view ID passed to
344 * {@link FragmentTransaction#add(int, Fragment) FragmentTransaction.add(int, Fragment)}.
345 * If the fragment was added with a container, setShowsDialog will be
346 * initialized to false; otherwise, it will be true.
347 *
348 * @param showsDialog If true, the fragment will be displayed in a Dialog.
349 * If false, no Dialog will be created and the fragment's view hierarchly
350 * left undisturbed.
351 */
352 public void setShowsDialog(boolean showsDialog) {
353 mShowsDialog = showsDialog;
354 }
355
356 /**
357 * Return the current value of {@link #setShowsDialog(boolean)}.
358 */
359 public boolean getShowsDialog() {
360 return mShowsDialog;
361 }
362
Dianne Hackborndd913a52010-07-22 12:17:04 -0700363 @Override
Adam Powell31479e32016-04-22 11:27:31 -0700364 public void onAttach(Context context) {
365 super.onAttach(context);
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800366 if (!mShownByMe) {
367 // If not explicitly shown through our API, take this as an
368 // indication that the dialog is no longer dismissed.
369 mDismissed = false;
370 }
371 }
372
373 @Override
374 public void onDetach() {
375 super.onDetach();
376 if (!mShownByMe && !mDismissed) {
377 // The fragment was not shown by a direct call here, it is not
378 // dismissed, and now it is being detached... well, okay, thou
379 // art now dismissed. Have fun.
380 mDismissed = true;
381 }
382 }
383
384 @Override
Dianne Hackborndd913a52010-07-22 12:17:04 -0700385 public void onCreate(Bundle savedInstanceState) {
386 super.onCreate(savedInstanceState);
Dianne Hackborn72778202010-08-20 18:26:01 -0700387
388 mShowsDialog = mContainerId == 0;
389
Dianne Hackborndd913a52010-07-22 12:17:04 -0700390 if (savedInstanceState != null) {
Dianne Hackborn72778202010-08-20 18:26:01 -0700391 mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);
392 mTheme = savedInstanceState.getInt(SAVED_THEME, 0);
393 mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);
394 mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
395 mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);
Dianne Hackborndd913a52010-07-22 12:17:04 -0700396 }
397 }
398
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800399 /** @hide */
400 @Override
401 public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
402 if (!mShowsDialog) {
403 return super.getLayoutInflater(savedInstanceState);
404 }
405
406 mDialog = onCreateDialog(savedInstanceState);
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800407 switch (mStyle) {
408 case STYLE_NO_INPUT:
409 mDialog.getWindow().addFlags(
410 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
411 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
412 // fall through...
413 case STYLE_NO_FRAME:
414 case STYLE_NO_TITLE:
415 mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
416 }
Dianne Hackborn25193d32011-03-01 15:01:30 -0800417 if (mDialog != null) {
418 return (LayoutInflater)mDialog.getContext().getSystemService(
419 Context.LAYOUT_INFLATER_SERVICE);
420 }
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700421 return (LayoutInflater) mHost.getContext().getSystemService(
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800422 Context.LAYOUT_INFLATER_SERVICE);
423 }
424
425 /**
426 * Override to build your own custom Dialog container. This is typically
427 * used to show an AlertDialog instead of a generic Dialog; when doing so,
428 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} does not need
429 * to be implemented since the AlertDialog takes care of its own content.
430 *
431 * <p>This method will be called after {@link #onCreate(Bundle)} and
432 * before {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. The
433 * default implementation simply instantiates and returns a {@link Dialog}
434 * class.
435 *
Dianne Hackbornf812fee2011-01-25 14:54:29 -0800436 * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener
437 * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener
438 * Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em>
439 * To find out about these events, override {@link #onCancel(DialogInterface)}
440 * and {@link #onDismiss(DialogInterface)}.</p>
441 *
Dianne Hackborn7187ccb2011-01-24 23:58:13 -0800442 * @param savedInstanceState The last saved instance state of the Fragment,
443 * or null if this is a freshly created Fragment.
444 *
445 * @return Return a new Dialog instance to be displayed by the Fragment.
446 */
Dianne Hackborndd913a52010-07-22 12:17:04 -0700447 public Dialog onCreateDialog(Bundle savedInstanceState) {
448 return new Dialog(getActivity(), getTheme());
449 }
450
451 public void onCancel(DialogInterface dialog) {
Dianne Hackborndd913a52010-07-22 12:17:04 -0700452 }
453
454 public void onDismiss(DialogInterface dialog) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800455 if (!mViewDestroyed) {
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700456 // Note: we need to use allowStateLoss, because the dialog
457 // dispatches this asynchronously so we can receive the call
458 // after the activity is paused. Worst case, when the user comes
459 // back to the activity they see the dialog again.
460 dismissInternal(true);
Dianne Hackborndef15372010-08-15 12:43:52 -0700461 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700462 }
463
464 @Override
465 public void onActivityCreated(Bundle savedInstanceState) {
466 super.onActivityCreated(savedInstanceState);
Dianne Hackborn72778202010-08-20 18:26:01 -0700467
468 if (!mShowsDialog) {
469 return;
470 }
471
Dianne Hackborndd913a52010-07-22 12:17:04 -0700472 View view = getView();
473 if (view != null) {
474 if (view.getParent() != null) {
Adam Powell31479e32016-04-22 11:27:31 -0700475 throw new IllegalStateException(
476 "DialogFragment can not be attached to a container view");
Dianne Hackborndd913a52010-07-22 12:17:04 -0700477 }
478 mDialog.setContentView(view);
479 }
Adam Powell31479e32016-04-22 11:27:31 -0700480 final Activity activity = getActivity();
481 if (activity != null) {
482 mDialog.setOwnerActivity(activity);
483 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700484 mDialog.setCancelable(mCancelable);
Dianne Hackbornf812fee2011-01-25 14:54:29 -0800485 if (!mDialog.takeCancelAndDismissListeners("DialogFragment", this, this)) {
486 throw new IllegalStateException(
487 "You can not set Dialog's OnCancelListener or OnDismissListener");
488 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700489 if (savedInstanceState != null) {
490 Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG);
491 if (dialogState != null) {
492 mDialog.onRestoreInstanceState(dialogState);
493 }
494 }
495 }
496
497 @Override
498 public void onStart() {
499 super.onStart();
Dianne Hackborndef15372010-08-15 12:43:52 -0700500 if (mDialog != null) {
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800501 mViewDestroyed = false;
Dianne Hackborndef15372010-08-15 12:43:52 -0700502 mDialog.show();
503 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700504 }
505
506 @Override
507 public void onSaveInstanceState(Bundle outState) {
508 super.onSaveInstanceState(outState);
509 if (mDialog != null) {
510 Bundle dialogState = mDialog.onSaveInstanceState();
511 if (dialogState != null) {
512 outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState);
513 }
514 }
Dianne Hackborn72778202010-08-20 18:26:01 -0700515 if (mStyle != STYLE_NORMAL) {
516 outState.putInt(SAVED_STYLE, mStyle);
517 }
518 if (mTheme != 0) {
519 outState.putInt(SAVED_THEME, mTheme);
520 }
521 if (!mCancelable) {
522 outState.putBoolean(SAVED_CANCELABLE, mCancelable);
523 }
524 if (!mShowsDialog) {
525 outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);
526 }
527 if (mBackStackId != -1) {
528 outState.putInt(SAVED_BACK_STACK_ID, mBackStackId);
529 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700530 }
531
532 @Override
533 public void onStop() {
534 super.onStop();
Dianne Hackborndef15372010-08-15 12:43:52 -0700535 if (mDialog != null) {
536 mDialog.hide();
537 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700538 }
539
540 /**
Dianne Hackborndef15372010-08-15 12:43:52 -0700541 * Remove dialog.
Dianne Hackborndd913a52010-07-22 12:17:04 -0700542 */
543 @Override
544 public void onDestroyView() {
545 super.onDestroyView();
Dianne Hackborndef15372010-08-15 12:43:52 -0700546 if (mDialog != null) {
547 // Set removed here because this dismissal is just to hide
548 // the dialog -- we don't want this to cause the fragment to
549 // actually be removed.
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800550 mViewDestroyed = true;
Dianne Hackborndef15372010-08-15 12:43:52 -0700551 mDialog.dismiss();
552 mDialog = null;
553 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700554 }
Dianne Hackbornbfe2e3f2011-03-01 16:40:54 -0800555
556 @Override
557 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
558 super.dump(prefix, fd, writer, args);
559 writer.print(prefix); writer.println("DialogFragment:");
560 writer.print(prefix); writer.print(" mStyle="); writer.print(mStyle);
561 writer.print(" mTheme=0x"); writer.println(Integer.toHexString(mTheme));
562 writer.print(prefix); writer.print(" mCancelable="); writer.print(mCancelable);
563 writer.print(" mShowsDialog="); writer.print(mShowsDialog);
564 writer.print(" mBackStackId="); writer.println(mBackStackId);
565 writer.print(prefix); writer.print(" mDialog="); writer.println(mDialog);
566 writer.print(prefix); writer.print(" mViewDestroyed="); writer.print(mViewDestroyed);
567 writer.print(" mDismissed="); writer.print(mDismissed);
568 writer.print(" mShownByMe="); writer.println(mShownByMe);
569 }
Dianne Hackborndd913a52010-07-22 12:17:04 -0700570}