19daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org/* 29daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * Copyright (C) 2011 The Android Open Source Project 39daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * 49daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * Licensed under the Apache License, Version 2.0 (the "License"); 59daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * you may not use this file except in compliance with the License. 69daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * You may obtain a copy of the License at 79daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * 89daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * http://www.apache.org/licenses/LICENSE-2.0 99daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * 101a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * Unless required by applicable law or agreed to in writing, software 111a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * distributed under the License is distributed on an "AS IS" BASIS, 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * See the License for the specific language governing permissions and 141a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * limitations under the License. 151a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org */ 169daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org 179daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.orgpackage android.support.v4.app; 184cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org 199daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.orgimport android.app.Activity; 20ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.orgimport android.app.Dialog; 211a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.orgimport android.content.Context; 2268400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.orgimport android.content.DialogInterface; 236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.orgimport android.os.Bundle; 24f2f8f3a43c5d7c7bd66afc6d9097ad5968df1596commit-bot@chromium.orgimport android.support.annotation.IntDef; 25f2f8f3a43c5d7c7bd66afc6d9097ad5968df1596commit-bot@chromium.orgimport android.support.annotation.NonNull; 26f2f8f3a43c5d7c7bd66afc6d9097ad5968df1596commit-bot@chromium.orgimport android.support.annotation.Nullable; 27b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgimport android.support.annotation.StyleRes; 28f2f8f3a43c5d7c7bd66afc6d9097ad5968df1596commit-bot@chromium.orgimport android.view.LayoutInflater; 294cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgimport android.view.View; 301a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.orgimport android.view.ViewGroup; 311a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.orgimport android.view.Window; 3268400767be5f72e4b9750ccc8bcf0078d42869a7senorblanco@chromium.orgimport android.view.WindowManager; 331a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 344cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgimport java.lang.annotation.Retention; 359daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.orgimport java.lang.annotation.RetentionPolicy; 366776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org 376776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org/** 381a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * Static library support version of the framework's {@link android.app.DialogFragment}. 391a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * Used to write apps that run on platforms prior to Android 3.0. When running 404cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org * on Android 3.0 or above, this implementation is still used; it does not try 411a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * to switch to the framework's implementation. See the framework SDK 421a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * documentation for a class overview. 431a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org */ 441a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.orgpublic class DialogFragment extends Fragment 45118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { 461a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org 471a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org /** @hide */ 481a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org @IntDef({STYLE_NORMAL, STYLE_NO_TITLE, STYLE_NO_FRAME, STYLE_NO_INPUT}) 491a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org @Retention(RetentionPolicy.SOURCE) 50cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org private @interface DialogStyle {} 51cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org 52cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org /** 531a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * Style for {@link #setStyle(int, int)}: a basic, 541a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * normal dialog. 551a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org */ 566776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org public static final int STYLE_NORMAL = 0; 576776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org 58e09244d463695cd9d2b089794ca18f59f1e4a621senorblanco@chromium.org /** 594cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org * Style for {@link #setStyle(int, int)}: don't include 60e09244d463695cd9d2b089794ca18f59f1e4a621senorblanco@chromium.org * a title area. 611a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org */ 626776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org public static final int STYLE_NO_TITLE = 1; 636776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org 641a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org /** 659daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * Style for {@link #setStyle(int, int)}: don't draw 669daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * any frame at all; the view hierarchy returned by {@link #onCreateView} 679daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * is entirely responsible for drawing the dialog. 68336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org */ 69336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org public static final int STYLE_NO_FRAME = 2; 70336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 71336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org /** 72336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org * Style for {@link #setStyle(int, int)}: like 73336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog. 74c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org * The user can not touch it, and its window will not receive input focus. 75336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org */ 76c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org public static final int STYLE_NO_INPUT = 3; 77336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 78336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState"; 799daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org private static final String SAVED_STYLE = "android:style"; 80c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org private static final String SAVED_THEME = "android:theme"; 819daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org private static final String SAVED_CANCELABLE = "android:cancelable"; 829daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org private static final String SAVED_SHOWS_DIALOG = "android:showsDialog"; 839daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org private static final String SAVED_BACK_STACK_ID = "android:backStackId"; 8406342a2666012f5d27faa7c2e230ae54f2dff311senorblanco@chromium.org 8506342a2666012f5d27faa7c2e230ae54f2dff311senorblanco@chromium.org int mStyle = STYLE_NORMAL; 8606342a2666012f5d27faa7c2e230ae54f2dff311senorblanco@chromium.org int mTheme = 0; 8729ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org boolean mCancelable = true; 8829ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org boolean mShowsDialog = true; 8929ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org int mBackStackId = -1; 9006342a2666012f5d27faa7c2e230ae54f2dff311senorblanco@chromium.org 919daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org Dialog mDialog; 929daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org boolean mViewDestroyed; 939daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org boolean mDismissed; 949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed boolean mShownByMe; 959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed public DialogFragment() { 979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 9824e06d5244ae96e440410e1d76e039983b2efac9senorblanco 999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed /** 1009fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * Call to customize the basic appearance and behavior of the 1018b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * fragment's dialog. This can be used for some common dialog behaviors, 1029daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * taking care of selecting flags, theme, and other options for you. The 1039daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * same effect can be achieve by manually setting Dialog and Window 1049daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * attributes yourself. Calling this after the fragment's Dialog is 1059daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * created will have no effect. 1061a4fb70c8a04db2d92ec821555f91218a989031dcommit-bot@chromium.org * 10724e06d5244ae96e440410e1d76e039983b2efac9senorblanco * @param style Selects a standard style: may be {@link #STYLE_NORMAL}, 10824e06d5244ae96e440410e1d76e039983b2efac9senorblanco * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or 1099daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * {@link #STYLE_NO_INPUT}. 1109daf96afb34313842d8d2c4abca73d954d2e9005senorblanco@chromium.org * @param theme Optional custom theme. If 0, an appropriate theme (based 111f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips * on the style) will be selected for you. 112f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips */ 113f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips public void setStyle(@DialogStyle int style, @StyleRes int theme) { 114f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips mStyle = style; 115f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { 116f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips mTheme = android.R.style.Theme_Panel; 117f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips } 118f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips if (theme != 0) { 119f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips mTheme = theme; 120f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips } 121f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips } 122f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 123 /** 124 * Display the dialog, adding the fragment to the given FragmentManager. This 125 * is a convenience for explicitly creating a transaction, adding the 126 * fragment to it with the given tag, and committing it. This does 127 * <em>not</em> add the transaction to the back stack. When the fragment 128 * is dismissed, a new transaction will be executed to remove it from 129 * the activity. 130 * @param manager The FragmentManager this fragment will be added to. 131 * @param tag The tag for this fragment, as per 132 * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. 133 */ 134 public void show(FragmentManager manager, String tag) { 135 mDismissed = false; 136 mShownByMe = true; 137 FragmentTransaction ft = manager.beginTransaction(); 138 ft.add(this, tag); 139 ft.commit(); 140 } 141 142 /** 143 * Display the dialog, adding the fragment using an existing transaction 144 * and then committing the transaction. 145 * @param transaction An existing transaction in which to add the fragment. 146 * @param tag The tag for this fragment, as per 147 * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. 148 * @return Returns the identifier of the committed transaction, as per 149 * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. 150 */ 151 public int show(FragmentTransaction transaction, String tag) { 152 mDismissed = false; 153 mShownByMe = true; 154 transaction.add(this, tag); 155 mViewDestroyed = false; 156 mBackStackId = transaction.commit(); 157 return mBackStackId; 158 } 159 160 /** 161 * Dismiss the fragment and its dialog. If the fragment was added to the 162 * back stack, all back stack state up to and including this entry will 163 * be popped. Otherwise, a new transaction will be committed to remove 164 * the fragment. 165 */ 166 public void dismiss() { 167 dismissInternal(false); 168 } 169 170 /** 171 * Version of {@link #dismiss()} that uses 172 * {@link FragmentTransaction#commitAllowingStateLoss() 173 * FragmentTransaction.commitAllowingStateLoss()}. See linked 174 * documentation for further details. 175 */ 176 public void dismissAllowingStateLoss() { 177 dismissInternal(true); 178 } 179 180 void dismissInternal(boolean allowStateLoss) { 181 if (mDismissed) { 182 return; 183 } 184 mDismissed = true; 185 mShownByMe = false; 186 if (mDialog != null) { 187 mDialog.dismiss(); 188 mDialog = null; 189 } 190 mViewDestroyed = true; 191 if (mBackStackId >= 0) { 192 getFragmentManager().popBackStack(mBackStackId, 193 FragmentManager.POP_BACK_STACK_INCLUSIVE); 194 mBackStackId = -1; 195 } else { 196 FragmentTransaction ft = getFragmentManager().beginTransaction(); 197 ft.remove(this); 198 if (allowStateLoss) { 199 ft.commitAllowingStateLoss(); 200 } else { 201 ft.commit(); 202 } 203 } 204 } 205 206 public Dialog getDialog() { 207 return mDialog; 208 } 209 210 @StyleRes 211 public int getTheme() { 212 return mTheme; 213 } 214 215 /** 216 * Control whether the shown Dialog is cancelable. Use this instead of 217 * directly calling {@link Dialog#setCancelable(boolean) 218 * Dialog.setCancelable(boolean)}, because DialogFragment needs to change 219 * its behavior based on this. 220 * 221 * @param cancelable If true, the dialog is cancelable. The default 222 * is true. 223 */ 224 public void setCancelable(boolean cancelable) { 225 mCancelable = cancelable; 226 if (mDialog != null) mDialog.setCancelable(cancelable); 227 } 228 229 /** 230 * Return the current value of {@link #setCancelable(boolean)}. 231 */ 232 public boolean isCancelable() { 233 return mCancelable; 234 } 235 236 /** 237 * Controls whether this fragment should be shown in a dialog. If not 238 * set, no Dialog will be created in {@link #onActivityCreated(Bundle)}, 239 * and the fragment's view hierarchy will thus not be added to it. This 240 * allows you to instead use it as a normal fragment (embedded inside of 241 * its activity). 242 * 243 * <p>This is normally set for you based on whether the fragment is 244 * associated with a container view ID passed to 245 * {@link FragmentTransaction#add(int, Fragment) FragmentTransaction.add(int, Fragment)}. 246 * If the fragment was added with a container, setShowsDialog will be 247 * initialized to false; otherwise, it will be true. 248 * 249 * @param showsDialog If true, the fragment will be displayed in a Dialog. 250 * If false, no Dialog will be created and the fragment's view hierarchly 251 * left undisturbed. 252 */ 253 public void setShowsDialog(boolean showsDialog) { 254 mShowsDialog = showsDialog; 255 } 256 257 /** 258 * Return the current value of {@link #setShowsDialog(boolean)}. 259 */ 260 public boolean getShowsDialog() { 261 return mShowsDialog; 262 } 263 264 @Override 265 public void onAttach(Activity activity) { 266 super.onAttach(activity); 267 if (!mShownByMe) { 268 // If not explicitly shown through our API, take this as an 269 // indication that the dialog is no longer dismissed. 270 mDismissed = false; 271 } 272 } 273 274 @Override 275 public void onDetach() { 276 super.onDetach(); 277 if (!mShownByMe && !mDismissed) { 278 // The fragment was not shown by a direct call here, it is not 279 // dismissed, and now it is being detached... well, okay, thou 280 // art now dismissed. Have fun. 281 mDismissed = true; 282 } 283 } 284 285 @Override 286 public void onCreate(@Nullable Bundle savedInstanceState) { 287 super.onCreate(savedInstanceState); 288 289 mShowsDialog = mContainerId == 0; 290 291 if (savedInstanceState != null) { 292 mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL); 293 mTheme = savedInstanceState.getInt(SAVED_THEME, 0); 294 mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true); 295 mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); 296 mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1); 297 } 298 299 } 300 301 /** @hide */ 302 @Override 303 public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { 304 if (!mShowsDialog) { 305 return super.getLayoutInflater(savedInstanceState); 306 } 307 308 mDialog = onCreateDialog(savedInstanceState); 309 310 if (mDialog != null) { 311 setupDialog(mDialog, mStyle); 312 313 return (LayoutInflater) mDialog.getContext().getSystemService( 314 Context.LAYOUT_INFLATER_SERVICE); 315 } 316 return (LayoutInflater) mHost.getContext().getSystemService( 317 Context.LAYOUT_INFLATER_SERVICE); 318 } 319 320 /** @hide */ 321 public void setupDialog(Dialog dialog, int style) { 322 switch (style) { 323 case STYLE_NO_INPUT: 324 dialog.getWindow().addFlags( 325 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 326 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); 327 // fall through... 328 case STYLE_NO_FRAME: 329 case STYLE_NO_TITLE: 330 dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 331 } 332 } 333 334 /** 335 * Override to build your own custom Dialog container. This is typically 336 * used to show an AlertDialog instead of a generic Dialog; when doing so, 337 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} does not need 338 * to be implemented since the AlertDialog takes care of its own content. 339 * 340 * <p>This method will be called after {@link #onCreate(Bundle)} and 341 * before {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. The 342 * default implementation simply instantiates and returns a {@link Dialog} 343 * class. 344 * 345 * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener 346 * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener 347 * Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em> 348 * To find out about these events, override {@link #onCancel(DialogInterface)} 349 * and {@link #onDismiss(DialogInterface)}.</p> 350 * 351 * @param savedInstanceState The last saved instance state of the Fragment, 352 * or null if this is a freshly created Fragment. 353 * 354 * @return Return a new Dialog instance to be displayed by the Fragment. 355 */ 356 @NonNull 357 public Dialog onCreateDialog(Bundle savedInstanceState) { 358 return new Dialog(getActivity(), getTheme()); 359 } 360 361 public void onCancel(DialogInterface dialog) { 362 } 363 364 public void onDismiss(DialogInterface dialog) { 365 if (!mViewDestroyed) { 366 // Note: we need to use allowStateLoss, because the dialog 367 // dispatches this asynchronously so we can receive the call 368 // after the activity is paused. Worst case, when the user comes 369 // back to the activity they see the dialog again. 370 dismissInternal(true); 371 } 372 } 373 374 @Override 375 public void onActivityCreated(Bundle savedInstanceState) { 376 super.onActivityCreated(savedInstanceState); 377 378 if (!mShowsDialog) { 379 return; 380 } 381 382 View view = getView(); 383 if (view != null) { 384 if (view.getParent() != null) { 385 throw new IllegalStateException("DialogFragment can not be attached to a container view"); 386 } 387 mDialog.setContentView(view); 388 } 389 mDialog.setOwnerActivity(getActivity()); 390 mDialog.setCancelable(mCancelable); 391 mDialog.setOnCancelListener(this); 392 mDialog.setOnDismissListener(this); 393 if (savedInstanceState != null) { 394 Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG); 395 if (dialogState != null) { 396 mDialog.onRestoreInstanceState(dialogState); 397 } 398 } 399 } 400 401 @Override 402 public void onStart() { 403 super.onStart(); 404 if (mDialog != null) { 405 mViewDestroyed = false; 406 mDialog.show(); 407 } 408 } 409 410 @Override 411 public void onSaveInstanceState(Bundle outState) { 412 super.onSaveInstanceState(outState); 413 if (mDialog != null) { 414 Bundle dialogState = mDialog.onSaveInstanceState(); 415 if (dialogState != null) { 416 outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState); 417 } 418 } 419 if (mStyle != STYLE_NORMAL) { 420 outState.putInt(SAVED_STYLE, mStyle); 421 } 422 if (mTheme != 0) { 423 outState.putInt(SAVED_THEME, mTheme); 424 } 425 if (!mCancelable) { 426 outState.putBoolean(SAVED_CANCELABLE, mCancelable); 427 } 428 if (!mShowsDialog) { 429 outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); 430 } 431 if (mBackStackId != -1) { 432 outState.putInt(SAVED_BACK_STACK_ID, mBackStackId); 433 } 434 } 435 436 @Override 437 public void onStop() { 438 super.onStop(); 439 if (mDialog != null) { 440 mDialog.hide(); 441 } 442 } 443 444 /** 445 * Remove dialog. 446 */ 447 @Override 448 public void onDestroyView() { 449 super.onDestroyView(); 450 if (mDialog != null) { 451 // Set removed here because this dismissal is just to hide 452 // the dialog -- we don't want this to cause the fragment to 453 // actually be removed. 454 mViewDestroyed = true; 455 mDialog.dismiss(); 456 mDialog = null; 457 } 458 } 459} 460