1 /* 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 17 package android.app; 18 19 import android.animation.Animator; 20 import android.annotation.CallSuper; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.StringRes; 24 import android.content.ComponentCallbacks2; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentSender; 28 import android.content.res.Configuration; 29 import android.content.res.Resources; 30 import android.content.res.TypedArray; 31 import android.os.Build; 32 import android.os.Build.VERSION_CODES; 33 import android.os.Bundle; 34 import android.os.Looper; 35 import android.os.Parcel; 36 import android.os.Parcelable; 37 import android.os.UserHandle; 38 import android.transition.Transition; 39 import android.transition.TransitionInflater; 40 import android.transition.TransitionSet; 41 import android.util.AndroidRuntimeException; 42 import android.util.ArrayMap; 43 import android.util.AttributeSet; 44 import android.util.DebugUtils; 45 import android.util.SparseArray; 46 import android.util.SuperNotCalledException; 47 import android.view.ContextMenu; 48 import android.view.ContextMenu.ContextMenuInfo; 49 import android.view.LayoutInflater; 50 import android.view.Menu; 51 import android.view.MenuInflater; 52 import android.view.MenuItem; 53 import android.view.View; 54 import android.view.View.OnCreateContextMenuListener; 55 import android.view.ViewGroup; 56 import android.widget.AdapterView; 57 58 import java.io.FileDescriptor; 59 import java.io.PrintWriter; 60 import java.lang.reflect.InvocationTargetException; 61 62 /** 63 * A Fragment is a piece of an application's user interface or behavior 64 * that can be placed in an {@link Activity}. Interaction with fragments 65 * is done through {@link FragmentManager}, which can be obtained via 66 * {@link Activity#getFragmentManager() Activity.getFragmentManager()} and 67 * {@link Fragment#getFragmentManager() Fragment.getFragmentManager()}. 68 * 69 * <p>The Fragment class can be used many ways to achieve a wide variety of 70 * results. In its core, it represents a particular operation or interface 71 * that is running within a larger {@link Activity}. A Fragment is closely 72 * tied to the Activity it is in, and can not be used apart from one. Though 73 * Fragment defines its own lifecycle, that lifecycle is dependent on its 74 * activity: if the activity is stopped, no fragments inside of it can be 75 * started; when the activity is destroyed, all fragments will be destroyed. 76 * 77 * <p>All subclasses of Fragment must include a public no-argument constructor. 78 * The framework will often re-instantiate a fragment class when needed, 79 * in particular during state restore, and needs to be able to find this 80 * constructor to instantiate it. If the no-argument constructor is not 81 * available, a runtime exception will occur in some cases during state 82 * restore. 83 * 84 * <p>Topics covered here: 85 * <ol> 86 * <li><a href="#OlderPlatforms">Older Platforms</a> 87 * <li><a href="#Lifecycle">Lifecycle</a> 88 * <li><a href="#Layout">Layout</a> 89 * <li><a href="#BackStack">Back Stack</a> 90 * </ol> 91 * 92 * <div class="special reference"> 93 * <h3>Developer Guides</h3> 94 * <p>For more information about using fragments, read the 95 * <a href="{@docRoot}guide/components/fragments.html">Fragments</a> developer guide.</p> 96 * </div> 97 * 98 * <a name="OlderPlatforms"></a> 99 * <h3>Older Platforms</h3> 100 * 101 * While the Fragment API was introduced in 102 * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, a version of the API 103 * at is also available for use on older platforms through 104 * {@link android.support.v4.app.FragmentActivity}. See the blog post 105 * <a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html"> 106 * Fragments For All</a> for more details. 107 * 108 * <a name="Lifecycle"></a> 109 * <h3>Lifecycle</h3> 110 * 111 * <p>Though a Fragment's lifecycle is tied to its owning activity, it has 112 * its own wrinkle on the standard activity lifecycle. It includes basic 113 * activity lifecycle methods such as {@link #onResume}, but also important 114 * are methods related to interactions with the activity and UI generation. 115 * 116 * <p>The core series of lifecycle methods that are called to bring a fragment 117 * up to resumed state (interacting with the user) are: 118 * 119 * <ol> 120 * <li> {@link #onAttach} called once the fragment is associated with its activity. 121 * <li> {@link #onCreate} called to do initial creation of the fragment. 122 * <li> {@link #onCreateView} creates and returns the view hierarchy associated 123 * with the fragment. 124 * <li> {@link #onActivityCreated} tells the fragment that its activity has 125 * completed its own {@link Activity#onCreate Activity.onCreate()}. 126 * <li> {@link #onViewStateRestored} tells the fragment that all of the saved 127 * state of its view hierarchy has been restored. 128 * <li> {@link #onStart} makes the fragment visible to the user (based on its 129 * containing activity being started). 130 * <li> {@link #onResume} makes the fragment begin interacting with the user 131 * (based on its containing activity being resumed). 132 * </ol> 133 * 134 * <p>As a fragment is no longer being used, it goes through a reverse 135 * series of callbacks: 136 * 137 * <ol> 138 * <li> {@link #onPause} fragment is no longer interacting with the user either 139 * because its activity is being paused or a fragment operation is modifying it 140 * in the activity. 141 * <li> {@link #onStop} fragment is no longer visible to the user either 142 * because its activity is being stopped or a fragment operation is modifying it 143 * in the activity. 144 * <li> {@link #onDestroyView} allows the fragment to clean up resources 145 * associated with its View. 146 * <li> {@link #onDestroy} called to do final cleanup of the fragment's state. 147 * <li> {@link #onDetach} called immediately prior to the fragment no longer 148 * being associated with its activity. 149 * </ol> 150 * 151 * <a name="Layout"></a> 152 * <h3>Layout</h3> 153 * 154 * <p>Fragments can be used as part of your application's layout, allowing 155 * you to better modularize your code and more easily adjust your user 156 * interface to the screen it is running on. As an example, we can look 157 * at a simple program consisting of a list of items, and display of the 158 * details of each item.</p> 159 * 160 * <p>An activity's layout XML can include <code><fragment></code> tags 161 * to embed fragment instances inside of the layout. For example, here is 162 * a simple layout that embeds one fragment:</p> 163 * 164 * {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} 165 * 166 * <p>The layout is installed in the activity in the normal way:</p> 167 * 168 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 169 * main} 170 * 171 * <p>The titles fragment, showing a list of titles, is fairly simple, relying 172 * on {@link ListFragment} for most of its work. Note the implementation of 173 * clicking an item: depending on the current activity's layout, it can either 174 * create and display a new fragment to show the details in-place (more about 175 * this later), or start a new activity to show the details.</p> 176 * 177 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 178 * titles} 179 * 180 * <p>The details fragment showing the contents of a selected item just 181 * displays a string of text based on an index of a string array built in to 182 * the app:</p> 183 * 184 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 185 * details} 186 * 187 * <p>In this case when the user clicks on a title, there is no details 188 * container in the current activity, so the titles fragment's click code will 189 * launch a new activity to display the details fragment:</p> 190 * 191 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 192 * details_activity} 193 * 194 * <p>However the screen may be large enough to show both the list of titles 195 * and details about the currently selected title. To use such a layout on 196 * a landscape screen, this alternative layout can be placed under layout-land:</p> 197 * 198 * {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} 199 * 200 * <p>Note how the prior code will adjust to this alternative UI flow: the titles 201 * fragment will now embed the details fragment inside of this activity, and the 202 * details activity will finish itself if it is running in a configuration 203 * where the details can be shown in-place. 204 * 205 * <p>When a configuration change causes the activity hosting these fragments 206 * to restart, its new instance may use a different layout that doesn't 207 * include the same fragments as the previous layout. In this case all of 208 * the previous fragments will still be instantiated and running in the new 209 * instance. However, any that are no longer associated with a <fragment> 210 * tag in the view hierarchy will not have their content view created 211 * and will return false from {@link #isInLayout}. (The code here also shows 212 * how you can determine if a fragment placed in a container is no longer 213 * running in a layout with that container and avoid creating its view hierarchy 214 * in that case.) 215 * 216 * <p>The attributes of the <fragment> tag are used to control the 217 * LayoutParams provided when attaching the fragment's view to the parent 218 * container. They can also be parsed by the fragment in {@link #onInflate} 219 * as parameters. 220 * 221 * <p>The fragment being instantiated must have some kind of unique identifier 222 * so that it can be re-associated with a previous instance if the parent 223 * activity needs to be destroyed and recreated. This can be provided these 224 * ways: 225 * 226 * <ul> 227 * <li>If nothing is explicitly supplied, the view ID of the container will 228 * be used. 229 * <li><code>android:tag</code> can be used in <fragment> to provide 230 * a specific tag name for the fragment. 231 * <li><code>android:id</code> can be used in <fragment> to provide 232 * a specific identifier for the fragment. 233 * </ul> 234 * 235 * <a name="BackStack"></a> 236 * <h3>Back Stack</h3> 237 * 238 * <p>The transaction in which fragments are modified can be placed on an 239 * internal back-stack of the owning activity. When the user presses back 240 * in the activity, any transactions on the back stack are popped off before 241 * the activity itself is finished. 242 * 243 * <p>For example, consider this simple fragment that is instantiated with 244 * an integer argument and displays that in a TextView in its UI:</p> 245 * 246 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java 247 * fragment} 248 * 249 * <p>A function that creates a new instance of the fragment, replacing 250 * whatever current fragment instance is being shown and pushing that change 251 * on to the back stack could be written as: 252 * 253 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java 254 * add_stack} 255 * 256 * <p>After each call to this function, a new entry is on the stack, and 257 * pressing back will pop it to return the user to whatever previous state 258 * the activity UI was in. 259 * 260 * @deprecated Use the <a href="{@docRoot}tools/extras/support-library.html">Support Library</a> 261 * {@link android.support.v4.app.Fragment} for consistent behavior across all devices 262 * and access to <a href="{@docRoot}topic/libraries/architecture/lifecycle.html">Lifecycle</a>. 263 */ 264 @Deprecated 265 public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener { 266 private static final ArrayMap<String, Class<?>> sClassMap = 267 new ArrayMap<String, Class<?>>(); 268 269 static final int INVALID_STATE = -1; // Invalid state used as a null value. 270 static final int INITIALIZING = 0; // Not yet created. 271 static final int CREATED = 1; // Created. 272 static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. 273 static final int STOPPED = 3; // Fully created, not started. 274 static final int STARTED = 4; // Created and started, not resumed. 275 static final int RESUMED = 5; // Created started and resumed. 276 277 private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet(); 278 279 int mState = INITIALIZING; 280 281 // When instantiated from saved state, this is the saved state. 282 Bundle mSavedFragmentState; 283 SparseArray<Parcelable> mSavedViewState; 284 285 // Index into active fragment array. 286 int mIndex = -1; 287 288 // Internal unique name for this fragment; 289 String mWho; 290 291 // Construction arguments; 292 Bundle mArguments; 293 294 // Target fragment. 295 Fragment mTarget; 296 297 // For use when retaining a fragment: this is the index of the last mTarget. 298 int mTargetIndex = -1; 299 300 // Target request code. 301 int mTargetRequestCode; 302 303 // True if the fragment is in the list of added fragments. 304 boolean mAdded; 305 306 // If set this fragment is being removed from its activity. 307 boolean mRemoving; 308 309 // Set to true if this fragment was instantiated from a layout file. 310 boolean mFromLayout; 311 312 // Set to true when the view has actually been inflated in its layout. 313 boolean mInLayout; 314 315 // True if this fragment has been restored from previously saved state. 316 boolean mRestored; 317 318 // True if performCreateView has been called and a matching call to performDestroyView 319 // has not yet happened. 320 boolean mPerformedCreateView; 321 322 // Number of active back stack entries this fragment is in. 323 int mBackStackNesting; 324 325 // The fragment manager we are associated with. Set as soon as the 326 // fragment is used in a transaction; cleared after it has been removed 327 // from all transactions. 328 FragmentManagerImpl mFragmentManager; 329 330 // Activity this fragment is attached to. 331 FragmentHostCallback mHost; 332 333 // Private fragment manager for child fragments inside of this one. 334 FragmentManagerImpl mChildFragmentManager; 335 336 // For use when restoring fragment state and descendant fragments are retained. 337 // This state is set by FragmentState.instantiate and cleared in onCreate. 338 FragmentManagerNonConfig mChildNonConfig; 339 340 // If this Fragment is contained in another Fragment, this is that container. 341 Fragment mParentFragment; 342 343 // The optional identifier for this fragment -- either the container ID if it 344 // was dynamically added to the view hierarchy, or the ID supplied in 345 // layout. 346 int mFragmentId; 347 348 // When a fragment is being dynamically added to the view hierarchy, this 349 // is the identifier of the parent container it is being added to. 350 int mContainerId; 351 352 // The optional named tag for this fragment -- usually used to find 353 // fragments that are not part of the layout. 354 String mTag; 355 356 // Set to true when the app has requested that this fragment be hidden 357 // from the user. 358 boolean mHidden; 359 360 // Set to true when the app has requested that this fragment be detached. 361 boolean mDetached; 362 363 // If set this fragment would like its instance retained across 364 // configuration changes. 365 boolean mRetainInstance; 366 367 // If set this fragment is being retained across the current config change. 368 boolean mRetaining; 369 370 // If set this fragment has menu items to contribute. 371 boolean mHasMenu; 372 373 // Set to true to allow the fragment's menu to be shown. 374 boolean mMenuVisible = true; 375 376 // Used to verify that subclasses call through to super class. 377 boolean mCalled; 378 379 // The parent container of the fragment after dynamically added to UI. 380 ViewGroup mContainer; 381 382 // The View generated for this fragment. 383 View mView; 384 385 // Whether this fragment should defer starting until after other fragments 386 // have been started and their loaders are finished. 387 boolean mDeferStart; 388 389 // Hint provided by the app that this fragment is currently visible to the user. 390 boolean mUserVisibleHint = true; 391 392 LoaderManagerImpl mLoaderManager; 393 boolean mLoadersStarted; 394 boolean mCheckedForLoaderManager; 395 396 // The animation and transition information for the fragment. This will be null 397 // unless the elements are explicitly accessed and should remain null for Fragments 398 // without Views. 399 AnimationInfo mAnimationInfo; 400 401 // True if the View was added, and its animation has yet to be run. This could 402 // also indicate that the fragment view hasn't been made visible, even if there is no 403 // animation for this fragment. 404 boolean mIsNewlyAdded; 405 406 // True if mHidden has been changed and the animation should be scheduled. 407 boolean mHiddenChanged; 408 409 // The cached value from onGetLayoutInflater(Bundle) that will be returned from 410 // getLayoutInflater() 411 LayoutInflater mLayoutInflater; 412 413 // Keep track of whether or not this Fragment has run performCreate(). Retained instance 414 // fragments can have mRetaining set to true without going through creation, so we must 415 // track it separately. 416 boolean mIsCreated; 417 418 /** 419 * State information that has been retrieved from a fragment instance 420 * through {@link FragmentManager#saveFragmentInstanceState(Fragment) 421 * FragmentManager.saveFragmentInstanceState}. 422 * 423 * @deprecated Use {@link android.support.v4.app.Fragment.SavedState} 424 */ 425 @Deprecated 426 public static class SavedState implements Parcelable { 427 final Bundle mState; 428 429 SavedState(Bundle state) { 430 mState = state; 431 } 432 433 SavedState(Parcel in, ClassLoader loader) { 434 mState = in.readBundle(); 435 if (loader != null && mState != null) { 436 mState.setClassLoader(loader); 437 } 438 } 439 440 @Override 441 public int describeContents() { 442 return 0; 443 } 444 445 @Override 446 public void writeToParcel(Parcel dest, int flags) { 447 dest.writeBundle(mState); 448 } 449 450 public static final Parcelable.ClassLoaderCreator<SavedState> CREATOR 451 = new Parcelable.ClassLoaderCreator<SavedState>() { 452 public SavedState createFromParcel(Parcel in) { 453 return new SavedState(in, null); 454 } 455 456 public SavedState createFromParcel(Parcel in, ClassLoader loader) { 457 return new SavedState(in, loader); 458 } 459 460 public SavedState[] newArray(int size) { 461 return new SavedState[size]; 462 } 463 }; 464 } 465 466 /** 467 * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when 468 * there is an instantiation failure. 469 * 470 * @deprecated Use {@link android.support.v4.app.Fragment.InstantiationException} 471 */ 472 @Deprecated 473 static public class InstantiationException extends AndroidRuntimeException { 474 public InstantiationException(String msg, Exception cause) { 475 super(msg, cause); 476 } 477 } 478 479 /** 480 * Default constructor. <strong>Every</strong> fragment must have an 481 * empty constructor, so it can be instantiated when restoring its 482 * activity's state. It is strongly recommended that subclasses do not 483 * have other constructors with parameters, since these constructors 484 * will not be called when the fragment is re-instantiated; instead, 485 * arguments can be supplied by the caller with {@link #setArguments} 486 * and later retrieved by the Fragment with {@link #getArguments}. 487 * 488 * <p>Applications should generally not implement a constructor. Prefer 489 * {@link #onAttach(Context)} instead. It is the first place application code can run where 490 * the fragment is ready to be used - the point where the fragment is actually associated with 491 * its context. Some applications may also want to implement {@link #onInflate} to retrieve 492 * attributes from a layout resource, although note this happens when the fragment is attached. 493 */ 494 public Fragment() { 495 } 496 497 /** 498 * Like {@link #instantiate(Context, String, Bundle)} but with a null 499 * argument Bundle. 500 */ 501 public static Fragment instantiate(Context context, String fname) { 502 return instantiate(context, fname, null); 503 } 504 505 /** 506 * Create a new instance of a Fragment with the given class name. This is 507 * the same as calling its empty constructor. 508 * 509 * @param context The calling context being used to instantiate the fragment. 510 * This is currently just used to get its ClassLoader. 511 * @param fname The class name of the fragment to instantiate. 512 * @param args Bundle of arguments to supply to the fragment, which it 513 * can retrieve with {@link #getArguments()}. May be null. 514 * @return Returns a new fragment instance. 515 * @throws InstantiationException If there is a failure in instantiating 516 * the given fragment class. This is a runtime exception; it is not 517 * normally expected to happen. 518 */ 519 public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) { 520 try { 521 Class<?> clazz = sClassMap.get(fname); 522 if (clazz == null) { 523 // Class not found in the cache, see if it's real, and try to add it 524 clazz = context.getClassLoader().loadClass(fname); 525 if (!Fragment.class.isAssignableFrom(clazz)) { 526 throw new InstantiationException("Trying to instantiate a class " + fname 527 + " that is not a Fragment", new ClassCastException()); 528 } 529 sClassMap.put(fname, clazz); 530 } 531 Fragment f = (Fragment) clazz.getConstructor().newInstance(); 532 if (args != null) { 533 args.setClassLoader(f.getClass().getClassLoader()); 534 f.setArguments(args); 535 } 536 return f; 537 } catch (ClassNotFoundException e) { 538 throw new InstantiationException("Unable to instantiate fragment " + fname 539 + ": make sure class name exists, is public, and has an" 540 + " empty constructor that is public", e); 541 } catch (java.lang.InstantiationException e) { 542 throw new InstantiationException("Unable to instantiate fragment " + fname 543 + ": make sure class name exists, is public, and has an" 544 + " empty constructor that is public", e); 545 } catch (IllegalAccessException e) { 546 throw new InstantiationException("Unable to instantiate fragment " + fname 547 + ": make sure class name exists, is public, and has an" 548 + " empty constructor that is public", e); 549 } catch (NoSuchMethodException e) { 550 throw new InstantiationException("Unable to instantiate fragment " + fname 551 + ": could not find Fragment constructor", e); 552 } catch (InvocationTargetException e) { 553 throw new InstantiationException("Unable to instantiate fragment " + fname 554 + ": calling Fragment constructor caused an exception", e); 555 } 556 } 557 558 final void restoreViewState(Bundle savedInstanceState) { 559 if (mSavedViewState != null) { 560 mView.restoreHierarchyState(mSavedViewState); 561 mSavedViewState = null; 562 } 563 mCalled = false; 564 onViewStateRestored(savedInstanceState); 565 if (!mCalled) { 566 throw new SuperNotCalledException("Fragment " + this 567 + " did not call through to super.onViewStateRestored()"); 568 } 569 } 570 571 final void setIndex(int index, Fragment parent) { 572 mIndex = index; 573 if (parent != null) { 574 mWho = parent.mWho + ":" + mIndex; 575 } else { 576 mWho = "android:fragment:" + mIndex; 577 } 578 } 579 580 final boolean isInBackStack() { 581 return mBackStackNesting > 0; 582 } 583 584 /** 585 * Subclasses can not override equals(). 586 */ 587 @Override final public boolean equals(Object o) { 588 return super.equals(o); 589 } 590 591 /** 592 * Subclasses can not override hashCode(). 593 */ 594 @Override final public int hashCode() { 595 return super.hashCode(); 596 } 597 598 @Override 599 public String toString() { 600 StringBuilder sb = new StringBuilder(128); 601 DebugUtils.buildShortClassTag(this, sb); 602 if (mIndex >= 0) { 603 sb.append(" #"); 604 sb.append(mIndex); 605 } 606 if (mFragmentId != 0) { 607 sb.append(" id=0x"); 608 sb.append(Integer.toHexString(mFragmentId)); 609 } 610 if (mTag != null) { 611 sb.append(" "); 612 sb.append(mTag); 613 } 614 sb.append('}'); 615 return sb.toString(); 616 } 617 618 /** 619 * Return the identifier this fragment is known by. This is either 620 * the android:id value supplied in a layout or the container view ID 621 * supplied when adding the fragment. 622 */ 623 final public int getId() { 624 return mFragmentId; 625 } 626 627 /** 628 * Get the tag name of the fragment, if specified. 629 */ 630 final public String getTag() { 631 return mTag; 632 } 633 634 /** 635 * Supply the construction arguments for this fragment. 636 * The arguments supplied here will be retained across fragment destroy and 637 * creation. 638 * 639 * <p>This method cannot be called if the fragment is added to a FragmentManager and 640 * if {@link #isStateSaved()} would return true. Prior to {@link Build.VERSION_CODES#O}, 641 * this method may only be called if the fragment has not yet been added to a FragmentManager. 642 * </p> 643 */ 644 public void setArguments(Bundle args) { 645 // The isStateSaved requirement below was only added in Android O and is compatible 646 // because it loosens previous requirements rather than making them more strict. 647 // See method javadoc. 648 if (mIndex >= 0 && isStateSaved()) { 649 throw new IllegalStateException("Fragment already active"); 650 } 651 mArguments = args; 652 } 653 654 /** 655 * Return the arguments supplied to {@link #setArguments}, if any. 656 */ 657 final public Bundle getArguments() { 658 return mArguments; 659 } 660 661 /** 662 * Returns true if this fragment is added and its state has already been saved 663 * by its host. Any operations that would change saved state should not be performed 664 * if this method returns true, and some operations such as {@link #setArguments(Bundle)} 665 * will fail. 666 * 667 * @return true if this fragment's state has already been saved by its host 668 */ 669 public final boolean isStateSaved() { 670 if (mFragmentManager == null) { 671 return false; 672 } 673 return mFragmentManager.isStateSaved(); 674 } 675 676 /** 677 * Set the initial saved state that this Fragment should restore itself 678 * from when first being constructed, as returned by 679 * {@link FragmentManager#saveFragmentInstanceState(Fragment) 680 * FragmentManager.saveFragmentInstanceState}. 681 * 682 * @param state The state the fragment should be restored from. 683 */ 684 public void setInitialSavedState(SavedState state) { 685 if (mIndex >= 0) { 686 throw new IllegalStateException("Fragment already active"); 687 } 688 mSavedFragmentState = state != null && state.mState != null 689 ? state.mState : null; 690 } 691 692 /** 693 * Optional target for this fragment. This may be used, for example, 694 * if this fragment is being started by another, and when done wants to 695 * give a result back to the first. The target set here is retained 696 * across instances via {@link FragmentManager#putFragment 697 * FragmentManager.putFragment()}. 698 * 699 * @param fragment The fragment that is the target of this one. 700 * @param requestCode Optional request code, for convenience if you 701 * are going to call back with {@link #onActivityResult(int, int, Intent)}. 702 */ 703 public void setTargetFragment(Fragment fragment, int requestCode) { 704 // Don't allow a caller to set a target fragment in another FragmentManager, 705 // but there's a snag: people do set target fragments before fragments get added. 706 // We'll have the FragmentManager check that for validity when we move 707 // the fragments to a valid state. 708 final FragmentManager mine = getFragmentManager(); 709 final FragmentManager theirs = fragment != null ? fragment.getFragmentManager() : null; 710 if (mine != null && theirs != null && mine != theirs) { 711 throw new IllegalArgumentException("Fragment " + fragment 712 + " must share the same FragmentManager to be set as a target fragment"); 713 } 714 715 // Don't let someone create a cycle. 716 for (Fragment check = fragment; check != null; check = check.getTargetFragment()) { 717 if (check == this) { 718 throw new IllegalArgumentException("Setting " + fragment + " as the target of " 719 + this + " would create a target cycle"); 720 } 721 } 722 mTarget = fragment; 723 mTargetRequestCode = requestCode; 724 } 725 726 /** 727 * Return the target fragment set by {@link #setTargetFragment}. 728 */ 729 final public Fragment getTargetFragment() { 730 return mTarget; 731 } 732 733 /** 734 * Return the target request code set by {@link #setTargetFragment}. 735 */ 736 final public int getTargetRequestCode() { 737 return mTargetRequestCode; 738 } 739 740 /** 741 * Return the {@link Context} this fragment is currently associated with. 742 */ 743 public Context getContext() { 744 return mHost == null ? null : mHost.getContext(); 745 } 746 747 /** 748 * Return the Activity this fragment is currently associated with. 749 */ 750 final public Activity getActivity() { 751 return mHost == null ? null : mHost.getActivity(); 752 } 753 754 /** 755 * Return the host object of this fragment. May return {@code null} if the fragment 756 * isn't currently being hosted. 757 */ 758 @Nullable 759 final public Object getHost() { 760 return mHost == null ? null : mHost.onGetHost(); 761 } 762 763 /** 764 * Return <code>getActivity().getResources()</code>. 765 */ 766 final public Resources getResources() { 767 if (mHost == null) { 768 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 769 } 770 return mHost.getContext().getResources(); 771 } 772 773 /** 774 * Return a localized, styled CharSequence from the application's package's 775 * default string table. 776 * 777 * @param resId Resource id for the CharSequence text 778 */ 779 public final CharSequence getText(@StringRes int resId) { 780 return getResources().getText(resId); 781 } 782 783 /** 784 * Return a localized string from the application's package's 785 * default string table. 786 * 787 * @param resId Resource id for the string 788 */ 789 public final String getString(@StringRes int resId) { 790 return getResources().getString(resId); 791 } 792 793 /** 794 * Return a localized formatted string from the application's package's 795 * default string table, substituting the format arguments as defined in 796 * {@link java.util.Formatter} and {@link java.lang.String#format}. 797 * 798 * @param resId Resource id for the format string 799 * @param formatArgs The format arguments that will be used for substitution. 800 */ 801 802 public final String getString(@StringRes int resId, Object... formatArgs) { 803 return getResources().getString(resId, formatArgs); 804 } 805 806 /** 807 * Return the FragmentManager for interacting with fragments associated 808 * with this fragment's activity. Note that this will be non-null slightly 809 * before {@link #getActivity()}, during the time from when the fragment is 810 * placed in a {@link FragmentTransaction} until it is committed and 811 * attached to its activity. 812 * 813 * <p>If this Fragment is a child of another Fragment, the FragmentManager 814 * returned here will be the parent's {@link #getChildFragmentManager()}. 815 */ 816 final public FragmentManager getFragmentManager() { 817 return mFragmentManager; 818 } 819 820 /** 821 * Return a private FragmentManager for placing and managing Fragments 822 * inside of this Fragment. 823 */ 824 final public FragmentManager getChildFragmentManager() { 825 if (mChildFragmentManager == null) { 826 instantiateChildFragmentManager(); 827 if (mState >= RESUMED) { 828 mChildFragmentManager.dispatchResume(); 829 } else if (mState >= STARTED) { 830 mChildFragmentManager.dispatchStart(); 831 } else if (mState >= ACTIVITY_CREATED) { 832 mChildFragmentManager.dispatchActivityCreated(); 833 } else if (mState >= CREATED) { 834 mChildFragmentManager.dispatchCreate(); 835 } 836 } 837 return mChildFragmentManager; 838 } 839 840 /** 841 * Returns the parent Fragment containing this Fragment. If this Fragment 842 * is attached directly to an Activity, returns null. 843 */ 844 final public Fragment getParentFragment() { 845 return mParentFragment; 846 } 847 848 /** 849 * Return true if the fragment is currently added to its activity. 850 */ 851 final public boolean isAdded() { 852 return mHost != null && mAdded; 853 } 854 855 /** 856 * Return true if the fragment has been explicitly detached from the UI. 857 * That is, {@link FragmentTransaction#detach(Fragment) 858 * FragmentTransaction.detach(Fragment)} has been used on it. 859 */ 860 final public boolean isDetached() { 861 return mDetached; 862 } 863 864 /** 865 * Return true if this fragment is currently being removed from its 866 * activity. This is <em>not</em> whether its activity is finishing, but 867 * rather whether it is in the process of being removed from its activity. 868 */ 869 final public boolean isRemoving() { 870 return mRemoving; 871 } 872 873 /** 874 * Return true if the layout is included as part of an activity view 875 * hierarchy via the <fragment> tag. This will always be true when 876 * fragments are created through the <fragment> tag, <em>except</em> 877 * in the case where an old fragment is restored from a previous state and 878 * it does not appear in the layout of the current state. 879 */ 880 final public boolean isInLayout() { 881 return mInLayout; 882 } 883 884 /** 885 * Return true if the fragment is in the resumed state. This is true 886 * for the duration of {@link #onResume()} and {@link #onPause()} as well. 887 */ 888 final public boolean isResumed() { 889 return mState >= RESUMED; 890 } 891 892 /** 893 * Return true if the fragment is currently visible to the user. This means 894 * it: (1) has been added, (2) has its view attached to the window, and 895 * (3) is not hidden. 896 */ 897 final public boolean isVisible() { 898 return isAdded() && !isHidden() && mView != null 899 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; 900 } 901 902 /** 903 * Return true if the fragment has been hidden. By default fragments 904 * are shown. You can find out about changes to this state with 905 * {@link #onHiddenChanged}. Note that the hidden state is orthogonal 906 * to other states -- that is, to be visible to the user, a fragment 907 * must be both started and not hidden. 908 */ 909 final public boolean isHidden() { 910 return mHidden; 911 } 912 913 /** 914 * Called when the hidden state (as returned by {@link #isHidden()} of 915 * the fragment has changed. Fragments start out not hidden; this will 916 * be called whenever the fragment changes state from that. 917 * @param hidden True if the fragment is now hidden, false otherwise. 918 */ 919 public void onHiddenChanged(boolean hidden) { 920 } 921 922 /** 923 * Control whether a fragment instance is retained across Activity 924 * re-creation (such as from a configuration change). This can only 925 * be used with fragments not in the back stack. If set, the fragment 926 * lifecycle will be slightly different when an activity is recreated: 927 * <ul> 928 * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still 929 * will be, because the fragment is being detached from its current activity). 930 * <li> {@link #onCreate(Bundle)} will not be called since the fragment 931 * is not being re-created. 932 * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b> 933 * still be called. 934 * </ul> 935 */ 936 public void setRetainInstance(boolean retain) { 937 mRetainInstance = retain; 938 } 939 940 final public boolean getRetainInstance() { 941 return mRetainInstance; 942 } 943 944 /** 945 * Report that this fragment would like to participate in populating 946 * the options menu by receiving a call to {@link #onCreateOptionsMenu} 947 * and related methods. 948 * 949 * @param hasMenu If true, the fragment has menu items to contribute. 950 */ 951 public void setHasOptionsMenu(boolean hasMenu) { 952 if (mHasMenu != hasMenu) { 953 mHasMenu = hasMenu; 954 if (isAdded() && !isHidden()) { 955 mFragmentManager.invalidateOptionsMenu(); 956 } 957 } 958 } 959 960 /** 961 * Set a hint for whether this fragment's menu should be visible. This 962 * is useful if you know that a fragment has been placed in your view 963 * hierarchy so that the user can not currently seen it, so any menu items 964 * it has should also not be shown. 965 * 966 * @param menuVisible The default is true, meaning the fragment's menu will 967 * be shown as usual. If false, the user will not see the menu. 968 */ 969 public void setMenuVisibility(boolean menuVisible) { 970 if (mMenuVisible != menuVisible) { 971 mMenuVisible = menuVisible; 972 if (mHasMenu && isAdded() && !isHidden()) { 973 mFragmentManager.invalidateOptionsMenu(); 974 } 975 } 976 } 977 978 /** 979 * Set a hint to the system about whether this fragment's UI is currently visible 980 * to the user. This hint defaults to true and is persistent across fragment instance 981 * state save and restore. 982 * 983 * <p>An app may set this to false to indicate that the fragment's UI is 984 * scrolled out of visibility or is otherwise not directly visible to the user. 985 * This may be used by the system to prioritize operations such as fragment lifecycle updates 986 * or loader ordering behavior.</p> 987 * 988 * <p><strong>Note:</strong> This method may be called outside of the fragment lifecycle 989 * and thus has no ordering guarantees with regard to fragment lifecycle method calls.</p> 990 * 991 * <p><strong>Note:</strong> Prior to Android N there was a platform bug that could cause 992 * <code>setUserVisibleHint</code> to bring a fragment up to the started state before its 993 * <code>FragmentTransaction</code> had been committed. As some apps relied on this behavior, 994 * it is preserved for apps that declare a <code>targetSdkVersion</code> of 23 or lower.</p> 995 * 996 * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), 997 * false if it is not. 998 */ 999 public void setUserVisibleHint(boolean isVisibleToUser) { 1000 // Prior to Android N we were simply checking if this fragment had a FragmentManager 1001 // set before we would trigger a deferred start. Unfortunately this also gets set before 1002 // a fragment transaction is committed, so if setUserVisibleHint was called before a 1003 // transaction commit, we would start the fragment way too early. FragmentPagerAdapter 1004 // triggers this situation. 1005 // Unfortunately some apps relied on this timing in overrides of setUserVisibleHint 1006 // on their own fragments, and expected, however erroneously, that after a call to 1007 // super.setUserVisibleHint their onStart methods had been run. 1008 // We preserve this behavior for apps targeting old platform versions below. 1009 boolean useBrokenAddedCheck = false; 1010 Context context = getContext(); 1011 if (mFragmentManager != null && mFragmentManager.mHost != null) { 1012 context = mFragmentManager.mHost.getContext(); 1013 } 1014 if (context != null) { 1015 useBrokenAddedCheck = context.getApplicationInfo().targetSdkVersion <= VERSION_CODES.M; 1016 } 1017 1018 final boolean performDeferredStart; 1019 if (useBrokenAddedCheck) { 1020 performDeferredStart = !mUserVisibleHint && isVisibleToUser && mState < STARTED 1021 && mFragmentManager != null; 1022 } else { 1023 performDeferredStart = !mUserVisibleHint && isVisibleToUser && mState < STARTED 1024 && mFragmentManager != null && isAdded(); 1025 } 1026 1027 if (performDeferredStart) { 1028 mFragmentManager.performPendingDeferredStart(this); 1029 } 1030 1031 mUserVisibleHint = isVisibleToUser; 1032 mDeferStart = mState < STARTED && !isVisibleToUser; 1033 } 1034 1035 /** 1036 * @return The current value of the user-visible hint on this fragment. 1037 * @see #setUserVisibleHint(boolean) 1038 */ 1039 public boolean getUserVisibleHint() { 1040 return mUserVisibleHint; 1041 } 1042 1043 /** 1044 * Return the LoaderManager for this fragment, creating it if needed. 1045 * 1046 * @deprecated Use {@link android.support.v4.app.Fragment#getLoaderManager()} 1047 */ 1048 @Deprecated 1049 public LoaderManager getLoaderManager() { 1050 if (mLoaderManager != null) { 1051 return mLoaderManager; 1052 } 1053 if (mHost == null) { 1054 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1055 } 1056 mCheckedForLoaderManager = true; 1057 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true); 1058 return mLoaderManager; 1059 } 1060 1061 /** 1062 * Call {@link Activity#startActivity(Intent)} from the fragment's 1063 * containing Activity. 1064 * 1065 * @param intent The intent to start. 1066 */ 1067 public void startActivity(Intent intent) { 1068 startActivity(intent, null); 1069 } 1070 1071 /** 1072 * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's 1073 * containing Activity. 1074 * 1075 * @param intent The intent to start. 1076 * @param options Additional options for how the Activity should be started. 1077 * See {@link android.content.Context#startActivity(Intent, Bundle)} 1078 * Context.startActivity(Intent, Bundle)} for more details. 1079 */ 1080 public void startActivity(Intent intent, Bundle options) { 1081 if (mHost == null) { 1082 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1083 } 1084 if (options != null) { 1085 mHost.onStartActivityFromFragment(this, intent, -1, options); 1086 } else { 1087 // Note we want to go through this call for compatibility with 1088 // applications that may have overridden the method. 1089 mHost.onStartActivityFromFragment(this, intent, -1, null /*options*/); 1090 } 1091 } 1092 1093 /** 1094 * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's 1095 * containing Activity. 1096 */ 1097 public void startActivityForResult(Intent intent, int requestCode) { 1098 startActivityForResult(intent, requestCode, null); 1099 } 1100 1101 /** 1102 * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's 1103 * containing Activity. 1104 */ 1105 public void startActivityForResult(Intent intent, int requestCode, Bundle options) { 1106 if (mHost == null) { 1107 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1108 } 1109 mHost.onStartActivityFromFragment(this, intent, requestCode, options); 1110 } 1111 1112 /** 1113 * @hide 1114 * Call {@link Activity#startActivityForResultAsUser(Intent, int, UserHandle)} from the 1115 * fragment's containing Activity. 1116 */ 1117 public void startActivityForResultAsUser( 1118 Intent intent, int requestCode, Bundle options, UserHandle user) { 1119 if (mHost == null) { 1120 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1121 } 1122 mHost.onStartActivityAsUserFromFragment(this, intent, requestCode, options, user); 1123 } 1124 1125 /** 1126 * Call {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int, 1127 * Bundle)} from the fragment's containing Activity. 1128 */ 1129 public void startIntentSenderForResult(IntentSender intent, int requestCode, 1130 @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 1131 Bundle options) throws IntentSender.SendIntentException { 1132 if (mHost == null) { 1133 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1134 } 1135 mHost.onStartIntentSenderFromFragment(this, intent, requestCode, fillInIntent, flagsMask, 1136 flagsValues, extraFlags, options); 1137 } 1138 1139 /** 1140 * Receive the result from a previous call to 1141 * {@link #startActivityForResult(Intent, int)}. This follows the 1142 * related Activity API as described there in 1143 * {@link Activity#onActivityResult(int, int, Intent)}. 1144 * 1145 * @param requestCode The integer request code originally supplied to 1146 * startActivityForResult(), allowing you to identify who this 1147 * result came from. 1148 * @param resultCode The integer result code returned by the child activity 1149 * through its setResult(). 1150 * @param data An Intent, which can return result data to the caller 1151 * (various data can be attached to Intent "extras"). 1152 */ 1153 public void onActivityResult(int requestCode, int resultCode, Intent data) { 1154 } 1155 1156 /** 1157 * Requests permissions to be granted to this application. These permissions 1158 * must be requested in your manifest, they should not be granted to your app, 1159 * and they should have protection level {@link android.content.pm.PermissionInfo 1160 * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by 1161 * the platform or a third-party app. 1162 * <p> 1163 * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL} 1164 * are granted at install time if requested in the manifest. Signature permissions 1165 * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at 1166 * install time if requested in the manifest and the signature of your app matches 1167 * the signature of the app declaring the permissions. 1168 * </p> 1169 * <p> 1170 * If your app does not have the requested permissions the user will be presented 1171 * with UI for accepting them. After the user has accepted or rejected the 1172 * requested permissions you will receive a callback on {@link 1173 * #onRequestPermissionsResult(int, String[], int[])} reporting whether the 1174 * permissions were granted or not. 1175 * </p> 1176 * <p> 1177 * Note that requesting a permission does not guarantee it will be granted and 1178 * your app should be able to run without having this permission. 1179 * </p> 1180 * <p> 1181 * This method may start an activity allowing the user to choose which permissions 1182 * to grant and which to reject. Hence, you should be prepared that your activity 1183 * may be paused and resumed. Further, granting some permissions may require 1184 * a restart of you application. In such a case, the system will recreate the 1185 * activity stack before delivering the result to {@link 1186 * #onRequestPermissionsResult(int, String[], int[])}. 1187 * </p> 1188 * <p> 1189 * When checking whether you have a permission you should use {@link 1190 * android.content.Context#checkSelfPermission(String)}. 1191 * </p> 1192 * <p> 1193 * Calling this API for permissions already granted to your app would show UI 1194 * to the user to decide whether the app can still hold these permissions. This 1195 * can be useful if the way your app uses data guarded by the permissions 1196 * changes significantly. 1197 * </p> 1198 * <p> 1199 * You cannot request a permission if your activity sets {@link 1200 * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to 1201 * <code>true</code> because in this case the activity would not receive 1202 * result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}. 1203 * </p> 1204 * <p> 1205 * A sample permissions request looks like this: 1206 * </p> 1207 * <code><pre><p> 1208 * private void showContacts() { 1209 * if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) 1210 * != PackageManager.PERMISSION_GRANTED) { 1211 * requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 1212 * PERMISSIONS_REQUEST_READ_CONTACTS); 1213 * } else { 1214 * doShowContacts(); 1215 * } 1216 * } 1217 * 1218 * {@literal @}Override 1219 * public void onRequestPermissionsResult(int requestCode, String[] permissions, 1220 * int[] grantResults) { 1221 * if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS 1222 * && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 1223 * doShowContacts(); 1224 * } 1225 * } 1226 * </code></pre></p> 1227 * 1228 * @param permissions The requested permissions. Must me non-null and not empty. 1229 * @param requestCode Application specific request code to match with a result 1230 * reported to {@link #onRequestPermissionsResult(int, String[], int[])}. 1231 * Should be >= 0. 1232 * 1233 * @see #onRequestPermissionsResult(int, String[], int[]) 1234 * @see android.content.Context#checkSelfPermission(String) 1235 */ 1236 public final void requestPermissions(@NonNull String[] permissions, int requestCode) { 1237 if (mHost == null) { 1238 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1239 } 1240 mHost.onRequestPermissionsFromFragment(this, permissions,requestCode); 1241 } 1242 1243 /** 1244 * Callback for the result from requesting permissions. This method 1245 * is invoked for every call on {@link #requestPermissions(String[], int)}. 1246 * <p> 1247 * <strong>Note:</strong> It is possible that the permissions request interaction 1248 * with the user is interrupted. In this case you will receive empty permissions 1249 * and results arrays which should be treated as a cancellation. 1250 * </p> 1251 * 1252 * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. 1253 * @param permissions The requested permissions. Never null. 1254 * @param grantResults The grant results for the corresponding permissions 1255 * which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED} 1256 * or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null. 1257 * 1258 * @see #requestPermissions(String[], int) 1259 */ 1260 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 1261 @NonNull int[] grantResults) { 1262 /* callback - do nothing */ 1263 } 1264 1265 /** 1266 * Gets whether you should show UI with rationale for requesting a permission. 1267 * You should do this only if you do not have the permission and the context in 1268 * which the permission is requested does not clearly communicate to the user 1269 * what would be the benefit from granting this permission. 1270 * <p> 1271 * For example, if you write a camera app, requesting the camera permission 1272 * would be expected by the user and no rationale for why it is requested is 1273 * needed. If however, the app needs location for tagging photos then a non-tech 1274 * savvy user may wonder how location is related to taking photos. In this case 1275 * you may choose to show UI with rationale of requesting this permission. 1276 * </p> 1277 * 1278 * @param permission A permission your app wants to request. 1279 * @return Whether you can show permission rationale UI. 1280 * 1281 * @see Context#checkSelfPermission(String) 1282 * @see #requestPermissions(String[], int) 1283 * @see #onRequestPermissionsResult(int, String[], int[]) 1284 */ 1285 public boolean shouldShowRequestPermissionRationale(@NonNull String permission) { 1286 if (mHost != null) { 1287 return mHost.getContext().getPackageManager() 1288 .shouldShowRequestPermissionRationale(permission); 1289 } 1290 return false; 1291 } 1292 1293 /** 1294 * Returns the LayoutInflater used to inflate Views of this Fragment. The default 1295 * implementation will throw an exception if the Fragment is not attached. 1296 * 1297 * @return The LayoutInflater used to inflate Views of this Fragment. 1298 */ 1299 public LayoutInflater onGetLayoutInflater(Bundle savedInstanceState) { 1300 if (mHost == null) { 1301 throw new IllegalStateException("onGetLayoutInflater() cannot be executed until the " 1302 + "Fragment is attached to the FragmentManager."); 1303 } 1304 final LayoutInflater result = mHost.onGetLayoutInflater(); 1305 if (mHost.onUseFragmentManagerInflaterFactory()) { 1306 getChildFragmentManager(); // Init if needed; use raw implementation below. 1307 result.setPrivateFactory(mChildFragmentManager.getLayoutInflaterFactory()); 1308 } 1309 return result; 1310 } 1311 1312 /** 1313 * Returns the cached LayoutInflater used to inflate Views of this Fragment. If 1314 * {@link #onGetLayoutInflater(Bundle)} has not been called {@link #onGetLayoutInflater(Bundle)} 1315 * will be called with a {@code null} argument and that value will be cached. 1316 * <p> 1317 * The cached LayoutInflater will be replaced immediately prior to 1318 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} and cleared immediately after 1319 * {@link #onDetach()}. 1320 * 1321 * @return The LayoutInflater used to inflate Views of this Fragment. 1322 */ 1323 public final LayoutInflater getLayoutInflater() { 1324 if (mLayoutInflater == null) { 1325 return performGetLayoutInflater(null); 1326 } 1327 return mLayoutInflater; 1328 } 1329 1330 /** 1331 * Calls {@link #onGetLayoutInflater(Bundle)} and caches the result for use by 1332 * {@link #getLayoutInflater()}. 1333 * 1334 * @param savedInstanceState If the fragment is being re-created from 1335 * a previous saved state, this is the state. 1336 * @return The LayoutInflater used to inflate Views of this Fragment. 1337 */ 1338 LayoutInflater performGetLayoutInflater(Bundle savedInstanceState) { 1339 LayoutInflater layoutInflater = onGetLayoutInflater(savedInstanceState); 1340 mLayoutInflater = layoutInflater; 1341 return mLayoutInflater; 1342 } 1343 1344 /** 1345 * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead. 1346 */ 1347 @Deprecated 1348 @CallSuper 1349 public void onInflate(AttributeSet attrs, Bundle savedInstanceState) { 1350 mCalled = true; 1351 } 1352 1353 /** 1354 * Called when a fragment is being created as part of a view layout 1355 * inflation, typically from setting the content view of an activity. This 1356 * may be called immediately after the fragment is created from a <fragment> 1357 * tag in a layout file. Note this is <em>before</em> the fragment's 1358 * {@link #onAttach(Activity)} has been called; all you should do here is 1359 * parse the attributes and save them away. 1360 * 1361 * <p>This is called every time the fragment is inflated, even if it is 1362 * being inflated into a new instance with saved state. It typically makes 1363 * sense to re-parse the parameters each time, to allow them to change with 1364 * different configurations.</p> 1365 * 1366 * <p>Here is a typical implementation of a fragment that can take parameters 1367 * both through attributes supplied here as well from {@link #getArguments()}:</p> 1368 * 1369 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java 1370 * fragment} 1371 * 1372 * <p>Note that parsing the XML attributes uses a "styleable" resource. The 1373 * declaration for the styleable used here is:</p> 1374 * 1375 * {@sample development/samples/ApiDemos/res/values/attrs.xml fragment_arguments} 1376 * 1377 * <p>The fragment can then be declared within its activity's content layout 1378 * through a tag like this:</p> 1379 * 1380 * {@sample development/samples/ApiDemos/res/layout/fragment_arguments.xml from_attributes} 1381 * 1382 * <p>This fragment can also be created dynamically from arguments given 1383 * at runtime in the arguments Bundle; here is an example of doing so at 1384 * creation of the containing activity:</p> 1385 * 1386 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java 1387 * create} 1388 * 1389 * @param context The Context that is inflating this fragment. 1390 * @param attrs The attributes at the tag where the fragment is 1391 * being created. 1392 * @param savedInstanceState If the fragment is being re-created from 1393 * a previous saved state, this is the state. 1394 */ 1395 @CallSuper 1396 public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) { 1397 onInflate(attrs, savedInstanceState); 1398 mCalled = true; 1399 1400 TypedArray a = context.obtainStyledAttributes(attrs, 1401 com.android.internal.R.styleable.Fragment); 1402 setEnterTransition(loadTransition(context, a, getEnterTransition(), null, 1403 com.android.internal.R.styleable.Fragment_fragmentEnterTransition)); 1404 setReturnTransition(loadTransition(context, a, getReturnTransition(), 1405 USE_DEFAULT_TRANSITION, 1406 com.android.internal.R.styleable.Fragment_fragmentReturnTransition)); 1407 setExitTransition(loadTransition(context, a, getExitTransition(), null, 1408 com.android.internal.R.styleable.Fragment_fragmentExitTransition)); 1409 1410 setReenterTransition(loadTransition(context, a, getReenterTransition(), 1411 USE_DEFAULT_TRANSITION, 1412 com.android.internal.R.styleable.Fragment_fragmentReenterTransition)); 1413 setSharedElementEnterTransition(loadTransition(context, a, 1414 getSharedElementEnterTransition(), null, 1415 com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition)); 1416 setSharedElementReturnTransition(loadTransition(context, a, 1417 getSharedElementReturnTransition(), USE_DEFAULT_TRANSITION, 1418 com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition)); 1419 boolean isEnterSet; 1420 boolean isReturnSet; 1421 if (mAnimationInfo == null) { 1422 isEnterSet = false; 1423 isReturnSet = false; 1424 } else { 1425 isEnterSet = mAnimationInfo.mAllowEnterTransitionOverlap != null; 1426 isReturnSet = mAnimationInfo.mAllowReturnTransitionOverlap != null; 1427 } 1428 if (!isEnterSet) { 1429 setAllowEnterTransitionOverlap(a.getBoolean( 1430 com.android.internal.R.styleable.Fragment_fragmentAllowEnterTransitionOverlap, 1431 true)); 1432 } 1433 if (!isReturnSet) { 1434 setAllowReturnTransitionOverlap(a.getBoolean( 1435 com.android.internal.R.styleable.Fragment_fragmentAllowReturnTransitionOverlap, 1436 true)); 1437 } 1438 a.recycle(); 1439 1440 final Activity hostActivity = mHost == null ? null : mHost.getActivity(); 1441 if (hostActivity != null) { 1442 mCalled = false; 1443 onInflate(hostActivity, attrs, savedInstanceState); 1444 } 1445 } 1446 1447 /** 1448 * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead. 1449 */ 1450 @Deprecated 1451 @CallSuper 1452 public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { 1453 mCalled = true; 1454 } 1455 1456 /** 1457 * Called when a fragment is attached as a child of this fragment. 1458 * 1459 * <p>This is called after the attached fragment's <code>onAttach</code> and before 1460 * the attached fragment's <code>onCreate</code> if the fragment has not yet had a previous 1461 * call to <code>onCreate</code>.</p> 1462 * 1463 * @param childFragment child fragment being attached 1464 */ 1465 public void onAttachFragment(Fragment childFragment) { 1466 } 1467 1468 /** 1469 * Called when a fragment is first attached to its context. 1470 * {@link #onCreate(Bundle)} will be called after this. 1471 */ 1472 @CallSuper 1473 public void onAttach(Context context) { 1474 mCalled = true; 1475 final Activity hostActivity = mHost == null ? null : mHost.getActivity(); 1476 if (hostActivity != null) { 1477 mCalled = false; 1478 onAttach(hostActivity); 1479 } 1480 } 1481 1482 /** 1483 * @deprecated Use {@link #onAttach(Context)} instead. 1484 */ 1485 @Deprecated 1486 @CallSuper 1487 public void onAttach(Activity activity) { 1488 mCalled = true; 1489 } 1490 1491 /** 1492 * Called when a fragment loads an animation. 1493 */ 1494 public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { 1495 return null; 1496 } 1497 1498 /** 1499 * Called to do initial creation of a fragment. This is called after 1500 * {@link #onAttach(Activity)} and before 1501 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, but is not called if the fragment 1502 * instance is retained across Activity re-creation (see {@link #setRetainInstance(boolean)}). 1503 * 1504 * <p>Note that this can be called while the fragment's activity is 1505 * still in the process of being created. As such, you can not rely 1506 * on things like the activity's content view hierarchy being initialized 1507 * at this point. If you want to do work once the activity itself is 1508 * created, see {@link #onActivityCreated(Bundle)}. 1509 * 1510 * <p>If your app's <code>targetSdkVersion</code> is {@link android.os.Build.VERSION_CODES#M} 1511 * or lower, child fragments being restored from the savedInstanceState are restored after 1512 * <code>onCreate</code> returns. When targeting {@link android.os.Build.VERSION_CODES#N} or 1513 * above and running on an N or newer platform version 1514 * they are restored by <code>Fragment.onCreate</code>.</p> 1515 * 1516 * @param savedInstanceState If the fragment is being re-created from 1517 * a previous saved state, this is the state. 1518 */ 1519 @CallSuper 1520 public void onCreate(@Nullable Bundle savedInstanceState) { 1521 mCalled = true; 1522 final Context context = getContext(); 1523 final int version = context != null ? context.getApplicationInfo().targetSdkVersion : 0; 1524 if (version >= Build.VERSION_CODES.N) { 1525 restoreChildFragmentState(savedInstanceState, true); 1526 if (mChildFragmentManager != null 1527 && !mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) { 1528 mChildFragmentManager.dispatchCreate(); 1529 } 1530 } 1531 } 1532 1533 void restoreChildFragmentState(@Nullable Bundle savedInstanceState, boolean provideNonConfig) { 1534 if (savedInstanceState != null) { 1535 Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG); 1536 if (p != null) { 1537 if (mChildFragmentManager == null) { 1538 instantiateChildFragmentManager(); 1539 } 1540 mChildFragmentManager.restoreAllState(p, provideNonConfig ? mChildNonConfig : null); 1541 mChildNonConfig = null; 1542 mChildFragmentManager.dispatchCreate(); 1543 } 1544 } 1545 } 1546 1547 /** 1548 * Called to have the fragment instantiate its user interface view. 1549 * This is optional, and non-graphical fragments can return null (which 1550 * is the default implementation). This will be called between 1551 * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. 1552 * 1553 * <p>If you return a View from here, you will later be called in 1554 * {@link #onDestroyView} when the view is being released. 1555 * 1556 * @param inflater The LayoutInflater object that can be used to inflate 1557 * any views in the fragment, 1558 * @param container If non-null, this is the parent view that the fragment's 1559 * UI should be attached to. The fragment should not add the view itself, 1560 * but this can be used to generate the LayoutParams of the view. 1561 * @param savedInstanceState If non-null, this fragment is being re-constructed 1562 * from a previous saved state as given here. 1563 * 1564 * @return Return the View for the fragment's UI, or null. 1565 */ 1566 @Nullable 1567 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 1568 Bundle savedInstanceState) { 1569 return null; 1570 } 1571 1572 /** 1573 * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 1574 * has returned, but before any saved state has been restored in to the view. 1575 * This gives subclasses a chance to initialize themselves once 1576 * they know their view hierarchy has been completely created. The fragment's 1577 * view hierarchy is not however attached to its parent at this point. 1578 * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 1579 * @param savedInstanceState If non-null, this fragment is being re-constructed 1580 * from a previous saved state as given here. 1581 */ 1582 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 1583 } 1584 1585 /** 1586 * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}), 1587 * if provided. 1588 * 1589 * @return The fragment's root view, or null if it has no layout. 1590 */ 1591 @Nullable 1592 public View getView() { 1593 return mView; 1594 } 1595 1596 /** 1597 * Called when the fragment's activity has been created and this 1598 * fragment's view hierarchy instantiated. It can be used to do final 1599 * initialization once these pieces are in place, such as retrieving 1600 * views or restoring state. It is also useful for fragments that use 1601 * {@link #setRetainInstance(boolean)} to retain their instance, 1602 * as this callback tells the fragment when it is fully associated with 1603 * the new activity instance. This is called after {@link #onCreateView} 1604 * and before {@link #onViewStateRestored(Bundle)}. 1605 * 1606 * @param savedInstanceState If the fragment is being re-created from 1607 * a previous saved state, this is the state. 1608 */ 1609 @CallSuper 1610 public void onActivityCreated(@Nullable Bundle savedInstanceState) { 1611 mCalled = true; 1612 } 1613 1614 /** 1615 * Called when all saved state has been restored into the view hierarchy 1616 * of the fragment. This can be used to do initialization based on saved 1617 * state that you are letting the view hierarchy track itself, such as 1618 * whether check box widgets are currently checked. This is called 1619 * after {@link #onActivityCreated(Bundle)} and before 1620 * {@link #onStart()}. 1621 * 1622 * @param savedInstanceState If the fragment is being re-created from 1623 * a previous saved state, this is the state. 1624 */ 1625 @CallSuper 1626 public void onViewStateRestored(Bundle savedInstanceState) { 1627 mCalled = true; 1628 } 1629 1630 /** 1631 * Called when the Fragment is visible to the user. This is generally 1632 * tied to {@link Activity#onStart() Activity.onStart} of the containing 1633 * Activity's lifecycle. 1634 */ 1635 @CallSuper 1636 public void onStart() { 1637 mCalled = true; 1638 1639 if (!mLoadersStarted) { 1640 mLoadersStarted = true; 1641 if (!mCheckedForLoaderManager) { 1642 mCheckedForLoaderManager = true; 1643 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); 1644 } else if (mLoaderManager != null) { 1645 mLoaderManager.doStart(); 1646 } 1647 } 1648 } 1649 1650 /** 1651 * Called when the fragment is visible to the user and actively running. 1652 * This is generally 1653 * tied to {@link Activity#onResume() Activity.onResume} of the containing 1654 * Activity's lifecycle. 1655 */ 1656 @CallSuper 1657 public void onResume() { 1658 mCalled = true; 1659 } 1660 1661 /** 1662 * Called to ask the fragment to save its current dynamic state, so it 1663 * can later be reconstructed in a new instance of its process is 1664 * restarted. If a new instance of the fragment later needs to be 1665 * created, the data you place in the Bundle here will be available 1666 * in the Bundle given to {@link #onCreate(Bundle)}, 1667 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and 1668 * {@link #onActivityCreated(Bundle)}. 1669 * 1670 * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle) 1671 * Activity.onSaveInstanceState(Bundle)} and most of the discussion there 1672 * applies here as well. Note however: <em>this method may be called 1673 * at any time before {@link #onDestroy()}</em>. There are many situations 1674 * where a fragment may be mostly torn down (such as when placed on the 1675 * back stack with no UI showing), but its state will not be saved until 1676 * its owning activity actually needs to save its state. 1677 * 1678 * @param outState Bundle in which to place your saved state. 1679 */ 1680 public void onSaveInstanceState(Bundle outState) { 1681 } 1682 1683 /** 1684 * Called when the Fragment's activity changes from fullscreen mode to multi-window mode and 1685 * visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the 1686 * containing Activity. This method provides the same configuration that will be sent in the 1687 * following {@link #onConfigurationChanged(Configuration)} call after the activity enters this 1688 * mode. 1689 * 1690 * @param isInMultiWindowMode True if the activity is in multi-window mode. 1691 * @param newConfig The new configuration of the activity with the state 1692 * {@param isInMultiWindowMode}. 1693 */ 1694 public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) { 1695 onMultiWindowModeChanged(isInMultiWindowMode); 1696 } 1697 1698 /** 1699 * Called when the Fragment's activity changes from fullscreen mode to multi-window mode and 1700 * visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the 1701 * containing Activity. 1702 * 1703 * @param isInMultiWindowMode True if the activity is in multi-window mode. 1704 * 1705 * @deprecated Use {@link #onMultiWindowModeChanged(boolean, Configuration)} instead. 1706 */ 1707 @Deprecated 1708 public void onMultiWindowModeChanged(boolean isInMultiWindowMode) { 1709 } 1710 1711 /** 1712 * Called by the system when the activity changes to and from picture-in-picture mode. This is 1713 * generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity. 1714 * This method provides the same configuration that will be sent in the following 1715 * {@link #onConfigurationChanged(Configuration)} call after the activity enters this mode. 1716 * 1717 * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode. 1718 * @param newConfig The new configuration of the activity with the state 1719 * {@param isInPictureInPictureMode}. 1720 */ 1721 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, 1722 Configuration newConfig) { 1723 onPictureInPictureModeChanged(isInPictureInPictureMode); 1724 } 1725 1726 /** 1727 * Called by the system when the activity changes to and from picture-in-picture mode. This is 1728 * generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity. 1729 * 1730 * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode. 1731 * 1732 * @deprecated Use {@link #onPictureInPictureModeChanged(boolean, Configuration)} instead. 1733 */ 1734 @Deprecated 1735 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { 1736 } 1737 1738 @CallSuper 1739 public void onConfigurationChanged(Configuration newConfig) { 1740 mCalled = true; 1741 } 1742 1743 /** 1744 * Called when the Fragment is no longer resumed. This is generally 1745 * tied to {@link Activity#onPause() Activity.onPause} of the containing 1746 * Activity's lifecycle. 1747 */ 1748 @CallSuper 1749 public void onPause() { 1750 mCalled = true; 1751 } 1752 1753 /** 1754 * Called when the Fragment is no longer started. This is generally 1755 * tied to {@link Activity#onStop() Activity.onStop} of the containing 1756 * Activity's lifecycle. 1757 */ 1758 @CallSuper 1759 public void onStop() { 1760 mCalled = true; 1761 } 1762 1763 @CallSuper 1764 public void onLowMemory() { 1765 mCalled = true; 1766 } 1767 1768 @CallSuper 1769 public void onTrimMemory(int level) { 1770 mCalled = true; 1771 } 1772 1773 /** 1774 * Called when the view previously created by {@link #onCreateView} has 1775 * been detached from the fragment. The next time the fragment needs 1776 * to be displayed, a new view will be created. This is called 1777 * after {@link #onStop()} and before {@link #onDestroy()}. It is called 1778 * <em>regardless</em> of whether {@link #onCreateView} returned a 1779 * non-null view. Internally it is called after the view's state has 1780 * been saved but before it has been removed from its parent. 1781 */ 1782 @CallSuper 1783 public void onDestroyView() { 1784 mCalled = true; 1785 } 1786 1787 /** 1788 * Called when the fragment is no longer in use. This is called 1789 * after {@link #onStop()} and before {@link #onDetach()}. 1790 */ 1791 @CallSuper 1792 public void onDestroy() { 1793 mCalled = true; 1794 //Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager 1795 // + " mLoaderManager=" + mLoaderManager); 1796 if (!mCheckedForLoaderManager) { 1797 mCheckedForLoaderManager = true; 1798 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); 1799 } 1800 if (mLoaderManager != null) { 1801 mLoaderManager.doDestroy(); 1802 } 1803 } 1804 1805 /** 1806 * Called by the fragment manager once this fragment has been removed, 1807 * so that we don't have any left-over state if the application decides 1808 * to re-use the instance. This only clears state that the framework 1809 * internally manages, not things the application sets. 1810 */ 1811 void initState() { 1812 mIndex = -1; 1813 mWho = null; 1814 mAdded = false; 1815 mRemoving = false; 1816 mFromLayout = false; 1817 mInLayout = false; 1818 mRestored = false; 1819 mBackStackNesting = 0; 1820 mFragmentManager = null; 1821 mChildFragmentManager = null; 1822 mHost = null; 1823 mFragmentId = 0; 1824 mContainerId = 0; 1825 mTag = null; 1826 mHidden = false; 1827 mDetached = false; 1828 mRetaining = false; 1829 mLoaderManager = null; 1830 mLoadersStarted = false; 1831 mCheckedForLoaderManager = false; 1832 } 1833 1834 /** 1835 * Called when the fragment is no longer attached to its activity. This is called after 1836 * {@link #onDestroy()}, except in the cases where the fragment instance is retained across 1837 * Activity re-creation (see {@link #setRetainInstance(boolean)}), in which case it is called 1838 * after {@link #onStop()}. 1839 */ 1840 @CallSuper 1841 public void onDetach() { 1842 mCalled = true; 1843 } 1844 1845 /** 1846 * Initialize the contents of the Activity's standard options menu. You 1847 * should place your menu items in to <var>menu</var>. For this method 1848 * to be called, you must have first called {@link #setHasOptionsMenu}. See 1849 * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} 1850 * for more information. 1851 * 1852 * @param menu The options menu in which you place your items. 1853 * 1854 * @see #setHasOptionsMenu 1855 * @see #onPrepareOptionsMenu 1856 * @see #onOptionsItemSelected 1857 */ 1858 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1859 } 1860 1861 /** 1862 * Prepare the Screen's standard options menu to be displayed. This is 1863 * called right before the menu is shown, every time it is shown. You can 1864 * use this method to efficiently enable/disable items or otherwise 1865 * dynamically modify the contents. See 1866 * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} 1867 * for more information. 1868 * 1869 * @param menu The options menu as last shown or first initialized by 1870 * onCreateOptionsMenu(). 1871 * 1872 * @see #setHasOptionsMenu 1873 * @see #onCreateOptionsMenu 1874 */ 1875 public void onPrepareOptionsMenu(Menu menu) { 1876 } 1877 1878 /** 1879 * Called when this fragment's option menu items are no longer being 1880 * included in the overall options menu. Receiving this call means that 1881 * the menu needed to be rebuilt, but this fragment's items were not 1882 * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)} 1883 * was not called). 1884 */ 1885 public void onDestroyOptionsMenu() { 1886 } 1887 1888 /** 1889 * This hook is called whenever an item in your options menu is selected. 1890 * The default implementation simply returns false to have the normal 1891 * processing happen (calling the item's Runnable or sending a message to 1892 * its Handler as appropriate). You can use this method for any items 1893 * for which you would like to do processing without those other 1894 * facilities. 1895 * 1896 * <p>Derived classes should call through to the base class for it to 1897 * perform the default menu handling. 1898 * 1899 * @param item The menu item that was selected. 1900 * 1901 * @return boolean Return false to allow normal menu processing to 1902 * proceed, true to consume it here. 1903 * 1904 * @see #onCreateOptionsMenu 1905 */ 1906 public boolean onOptionsItemSelected(MenuItem item) { 1907 return false; 1908 } 1909 1910 /** 1911 * This hook is called whenever the options menu is being closed (either by the user canceling 1912 * the menu with the back/menu button, or when an item is selected). 1913 * 1914 * @param menu The options menu as last shown or first initialized by 1915 * onCreateOptionsMenu(). 1916 */ 1917 public void onOptionsMenuClosed(Menu menu) { 1918 } 1919 1920 /** 1921 * Called when a context menu for the {@code view} is about to be shown. 1922 * Unlike {@link #onCreateOptionsMenu}, this will be called every 1923 * time the context menu is about to be shown and should be populated for 1924 * the view (or item inside the view for {@link AdapterView} subclasses, 1925 * this can be found in the {@code menuInfo})). 1926 * <p> 1927 * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an 1928 * item has been selected. 1929 * <p> 1930 * The default implementation calls up to 1931 * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though 1932 * you can not call this implementation if you don't want that behavior. 1933 * <p> 1934 * It is not safe to hold onto the context menu after this method returns. 1935 * {@inheritDoc} 1936 */ 1937 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 1938 getActivity().onCreateContextMenu(menu, v, menuInfo); 1939 } 1940 1941 /** 1942 * Registers a context menu to be shown for the given view (multiple views 1943 * can show the context menu). This method will set the 1944 * {@link OnCreateContextMenuListener} on the view to this fragment, so 1945 * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be 1946 * called when it is time to show the context menu. 1947 * 1948 * @see #unregisterForContextMenu(View) 1949 * @param view The view that should show a context menu. 1950 */ 1951 public void registerForContextMenu(View view) { 1952 view.setOnCreateContextMenuListener(this); 1953 } 1954 1955 /** 1956 * Prevents a context menu to be shown for the given view. This method will 1957 * remove the {@link OnCreateContextMenuListener} on the view. 1958 * 1959 * @see #registerForContextMenu(View) 1960 * @param view The view that should stop showing a context menu. 1961 */ 1962 public void unregisterForContextMenu(View view) { 1963 view.setOnCreateContextMenuListener(null); 1964 } 1965 1966 /** 1967 * This hook is called whenever an item in a context menu is selected. The 1968 * default implementation simply returns false to have the normal processing 1969 * happen (calling the item's Runnable or sending a message to its Handler 1970 * as appropriate). You can use this method for any items for which you 1971 * would like to do processing without those other facilities. 1972 * <p> 1973 * Use {@link MenuItem#getMenuInfo()} to get extra information set by the 1974 * View that added this menu item. 1975 * <p> 1976 * Derived classes should call through to the base class for it to perform 1977 * the default menu handling. 1978 * 1979 * @param item The context menu item that was selected. 1980 * @return boolean Return false to allow normal context menu processing to 1981 * proceed, true to consume it here. 1982 */ 1983 public boolean onContextItemSelected(MenuItem item) { 1984 return false; 1985 } 1986 1987 /** 1988 * When custom transitions are used with Fragments, the enter transition callback 1989 * is called when this Fragment is attached or detached when not popping the back stack. 1990 * 1991 * @param callback Used to manipulate the shared element transitions on this Fragment 1992 * when added not as a pop from the back stack. 1993 */ 1994 public void setEnterSharedElementCallback(SharedElementCallback callback) { 1995 if (callback == null) { 1996 if (mAnimationInfo == null) { 1997 return; // already a null callback 1998 } 1999 callback = SharedElementCallback.NULL_CALLBACK; 2000 } 2001 ensureAnimationInfo().mEnterTransitionCallback = callback; 2002 } 2003 2004 /** 2005 * When custom transitions are used with Fragments, the exit transition callback 2006 * is called when this Fragment is attached or detached when popping the back stack. 2007 * 2008 * @param callback Used to manipulate the shared element transitions on this Fragment 2009 * when added as a pop from the back stack. 2010 */ 2011 public void setExitSharedElementCallback(SharedElementCallback callback) { 2012 if (callback == null) { 2013 if (mAnimationInfo == null) { 2014 return; // already a null callback 2015 } 2016 callback = SharedElementCallback.NULL_CALLBACK; 2017 } 2018 ensureAnimationInfo().mExitTransitionCallback = callback; 2019 } 2020 2021 /** 2022 * Sets the Transition that will be used to move Views into the initial scene. The entering 2023 * Views will be those that are regular Views or ViewGroups that have 2024 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 2025 * {@link android.transition.Visibility} as entering is governed by changing visibility from 2026 * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null, 2027 * entering Views will remain unaffected. 2028 * 2029 * @param transition The Transition to use to move Views into the initial Scene. 2030 * @attr ref android.R.styleable#Fragment_fragmentEnterTransition 2031 */ 2032 public void setEnterTransition(Transition transition) { 2033 if (shouldChangeTransition(transition, null)) { 2034 ensureAnimationInfo().mEnterTransition = transition; 2035 } 2036 } 2037 2038 /** 2039 * Returns the Transition that will be used to move Views into the initial scene. The entering 2040 * Views will be those that are regular Views or ViewGroups that have 2041 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 2042 * {@link android.transition.Visibility} as entering is governed by changing visibility from 2043 * {@link View#INVISIBLE} to {@link View#VISIBLE}. 2044 * 2045 * @return the Transition to use to move Views into the initial Scene. 2046 * @attr ref android.R.styleable#Fragment_fragmentEnterTransition 2047 */ 2048 public Transition getEnterTransition() { 2049 if (mAnimationInfo == null) { 2050 return null; 2051 } 2052 return mAnimationInfo.mEnterTransition; 2053 } 2054 2055 /** 2056 * Sets the Transition that will be used to move Views out of the scene when the Fragment is 2057 * preparing to be removed, hidden, or detached because of popping the back stack. The exiting 2058 * Views will be those that are regular Views or ViewGroups that have 2059 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 2060 * {@link android.transition.Visibility} as entering is governed by changing visibility from 2061 * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, 2062 * entering Views will remain unaffected. If nothing is set, the default will be to 2063 * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}. 2064 * 2065 * @param transition The Transition to use to move Views out of the Scene when the Fragment 2066 * is preparing to close. 2067 * @attr ref android.R.styleable#Fragment_fragmentExitTransition 2068 */ 2069 public void setReturnTransition(Transition transition) { 2070 if (shouldChangeTransition(transition, USE_DEFAULT_TRANSITION)) { 2071 ensureAnimationInfo().mReturnTransition = transition; 2072 } 2073 } 2074 2075 /** 2076 * Returns the Transition that will be used to move Views out of the scene when the Fragment is 2077 * preparing to be removed, hidden, or detached because of popping the back stack. The exiting 2078 * Views will be those that are regular Views or ViewGroups that have 2079 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 2080 * {@link android.transition.Visibility} as entering is governed by changing visibility from 2081 * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, 2082 * entering Views will remain unaffected. 2083 * 2084 * @return the Transition to use to move Views out of the Scene when the Fragment 2085 * is preparing to close. 2086 * @attr ref android.R.styleable#Fragment_fragmentExitTransition 2087 */ 2088 public Transition getReturnTransition() { 2089 if (mAnimationInfo == null) { 2090 return null; 2091 } 2092 return mAnimationInfo.mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition() 2093 : mAnimationInfo.mReturnTransition; 2094 } 2095 2096 /** 2097 * Sets the Transition that will be used to move Views out of the scene when the 2098 * fragment is removed, hidden, or detached when not popping the back stack. 2099 * The exiting Views will be those that are regular Views or ViewGroups that 2100 * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 2101 * {@link android.transition.Visibility} as exiting is governed by changing visibility 2102 * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will 2103 * remain unaffected. 2104 * 2105 * @param transition The Transition to use to move Views out of the Scene when the Fragment 2106 * is being closed not due to popping the back stack. 2107 * @attr ref android.R.styleable#Fragment_fragmentExitTransition 2108 */ 2109 public void setExitTransition(Transition transition) { 2110 if (shouldChangeTransition(transition, null)) { 2111 ensureAnimationInfo().mExitTransition = transition; 2112 } 2113 } 2114 2115 /** 2116 * Returns the Transition that will be used to move Views out of the scene when the 2117 * fragment is removed, hidden, or detached when not popping the back stack. 2118 * The exiting Views will be those that are regular Views or ViewGroups that 2119 * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 2120 * {@link android.transition.Visibility} as exiting is governed by changing visibility 2121 * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will 2122 * remain unaffected. 2123 * 2124 * @return the Transition to use to move Views out of the Scene when the Fragment 2125 * is being closed not due to popping the back stack. 2126 * @attr ref android.R.styleable#Fragment_fragmentExitTransition 2127 */ 2128 public Transition getExitTransition() { 2129 if (mAnimationInfo == null) { 2130 return null; 2131 } 2132 return mAnimationInfo.mExitTransition; 2133 } 2134 2135 /** 2136 * Sets the Transition that will be used to move Views in to the scene when returning due 2137 * to popping a back stack. The entering Views will be those that are regular Views 2138 * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions 2139 * will extend {@link android.transition.Visibility} as exiting is governed by changing 2140 * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, 2141 * the views will remain unaffected. If nothing is set, the default will be to use the same 2142 * transition as {@link #setExitTransition(android.transition.Transition)}. 2143 * 2144 * @param transition The Transition to use to move Views into the scene when reentering from a 2145 * previously-started Activity. 2146 * @attr ref android.R.styleable#Fragment_fragmentReenterTransition 2147 */ 2148 public void setReenterTransition(Transition transition) { 2149 if (shouldChangeTransition(transition, USE_DEFAULT_TRANSITION)) { 2150 ensureAnimationInfo().mReenterTransition = transition; 2151 } 2152 } 2153 2154 /** 2155 * Returns the Transition that will be used to move Views in to the scene when returning due 2156 * to popping a back stack. The entering Views will be those that are regular Views 2157 * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions 2158 * will extend {@link android.transition.Visibility} as exiting is governed by changing 2159 * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, 2160 * the views will remain unaffected. If nothing is set, the default will be to use the same 2161 * transition as {@link #setExitTransition(android.transition.Transition)}. 2162 * 2163 * @return the Transition to use to move Views into the scene when reentering from a 2164 * previously-started Activity. 2165 * @attr ref android.R.styleable#Fragment_fragmentReenterTransition 2166 */ 2167 public Transition getReenterTransition() { 2168 if (mAnimationInfo == null) { 2169 return null; 2170 } 2171 return mAnimationInfo.mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition() 2172 : mAnimationInfo.mReenterTransition; 2173 } 2174 2175 /** 2176 * Sets the Transition that will be used for shared elements transferred into the content 2177 * Scene. Typical Transitions will affect size and location, such as 2178 * {@link android.transition.ChangeBounds}. A null 2179 * value will cause transferred shared elements to blink to the final position. 2180 * 2181 * @param transition The Transition to use for shared elements transferred into the content 2182 * Scene. 2183 * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition 2184 */ 2185 public void setSharedElementEnterTransition(Transition transition) { 2186 if (shouldChangeTransition(transition, null)) { 2187 ensureAnimationInfo().mSharedElementEnterTransition = transition; 2188 } 2189 } 2190 2191 /** 2192 * Returns the Transition that will be used for shared elements transferred into the content 2193 * Scene. Typical Transitions will affect size and location, such as 2194 * {@link android.transition.ChangeBounds}. A null 2195 * value will cause transferred shared elements to blink to the final position. 2196 * 2197 * @return The Transition to use for shared elements transferred into the content 2198 * Scene. 2199 * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition 2200 */ 2201 public Transition getSharedElementEnterTransition() { 2202 if (mAnimationInfo == null) { 2203 return null; 2204 } 2205 return mAnimationInfo.mSharedElementEnterTransition; 2206 } 2207 2208 /** 2209 * Sets the Transition that will be used for shared elements transferred back during a 2210 * pop of the back stack. This Transition acts in the leaving Fragment. 2211 * Typical Transitions will affect size and location, such as 2212 * {@link android.transition.ChangeBounds}. A null 2213 * value will cause transferred shared elements to blink to the final position. 2214 * If no value is set, the default will be to use the same value as 2215 * {@link #setSharedElementEnterTransition(android.transition.Transition)}. 2216 * 2217 * @param transition The Transition to use for shared elements transferred out of the content 2218 * Scene. 2219 * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition 2220 */ 2221 public void setSharedElementReturnTransition(Transition transition) { 2222 if (shouldChangeTransition(transition, USE_DEFAULT_TRANSITION)) { 2223 ensureAnimationInfo().mSharedElementReturnTransition = transition; 2224 } 2225 } 2226 2227 /** 2228 * Return the Transition that will be used for shared elements transferred back during a 2229 * pop of the back stack. This Transition acts in the leaving Fragment. 2230 * Typical Transitions will affect size and location, such as 2231 * {@link android.transition.ChangeBounds}. A null 2232 * value will cause transferred shared elements to blink to the final position. 2233 * If no value is set, the default will be to use the same value as 2234 * {@link #setSharedElementEnterTransition(android.transition.Transition)}. 2235 * 2236 * @return The Transition to use for shared elements transferred out of the content 2237 * Scene. 2238 * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition 2239 */ 2240 public Transition getSharedElementReturnTransition() { 2241 if (mAnimationInfo == null) { 2242 return null; 2243 } 2244 return mAnimationInfo.mSharedElementReturnTransition == USE_DEFAULT_TRANSITION 2245 ? getSharedElementEnterTransition() 2246 : mAnimationInfo.mSharedElementReturnTransition; 2247 } 2248 2249 /** 2250 * Sets whether the the exit transition and enter transition overlap or not. 2251 * When true, the enter transition will start as soon as possible. When false, the 2252 * enter transition will wait until the exit transition completes before starting. 2253 * 2254 * @param allow true to start the enter transition when possible or false to 2255 * wait until the exiting transition completes. 2256 * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap 2257 */ 2258 public void setAllowEnterTransitionOverlap(boolean allow) { 2259 ensureAnimationInfo().mAllowEnterTransitionOverlap = allow; 2260 } 2261 2262 /** 2263 * Returns whether the the exit transition and enter transition overlap or not. 2264 * When true, the enter transition will start as soon as possible. When false, the 2265 * enter transition will wait until the exit transition completes before starting. 2266 * 2267 * @return true when the enter transition should start as soon as possible or false to 2268 * when it should wait until the exiting transition completes. 2269 * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap 2270 */ 2271 public boolean getAllowEnterTransitionOverlap() { 2272 return (mAnimationInfo == null || mAnimationInfo.mAllowEnterTransitionOverlap == null) 2273 ? true : mAnimationInfo.mAllowEnterTransitionOverlap; 2274 } 2275 2276 /** 2277 * Sets whether the the return transition and reenter transition overlap or not. 2278 * When true, the reenter transition will start as soon as possible. When false, the 2279 * reenter transition will wait until the return transition completes before starting. 2280 * 2281 * @param allow true to start the reenter transition when possible or false to wait until the 2282 * return transition completes. 2283 * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap 2284 */ 2285 public void setAllowReturnTransitionOverlap(boolean allow) { 2286 ensureAnimationInfo().mAllowReturnTransitionOverlap = allow; 2287 } 2288 2289 /** 2290 * Returns whether the the return transition and reenter transition overlap or not. 2291 * When true, the reenter transition will start as soon as possible. When false, the 2292 * reenter transition will wait until the return transition completes before starting. 2293 * 2294 * @return true to start the reenter transition when possible or false to wait until the 2295 * return transition completes. 2296 * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap 2297 */ 2298 public boolean getAllowReturnTransitionOverlap() { 2299 return (mAnimationInfo == null || mAnimationInfo.mAllowReturnTransitionOverlap == null) 2300 ? true : mAnimationInfo.mAllowReturnTransitionOverlap; 2301 } 2302 2303 /** 2304 * Postpone the entering Fragment transition until {@link #startPostponedEnterTransition()} 2305 * or {@link FragmentManager#executePendingTransactions()} has been called. 2306 * <p> 2307 * This method gives the Fragment the ability to delay Fragment animations 2308 * until all data is loaded. Until then, the added, shown, and 2309 * attached Fragments will be INVISIBLE and removed, hidden, and detached Fragments won't 2310 * be have their Views removed. The transaction runs when all postponed added Fragments in the 2311 * transaction have called {@link #startPostponedEnterTransition()}. 2312 * <p> 2313 * This method should be called before being added to the FragmentTransaction or 2314 * in {@link #onCreate(Bundle)}, {@link #onAttach(Context)}, or 2315 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}}. 2316 * {@link #startPostponedEnterTransition()} must be called to allow the Fragment to 2317 * start the transitions. 2318 * <p> 2319 * When a FragmentTransaction is started that may affect a postponed FragmentTransaction, 2320 * based on which containers are in their operations, the postponed FragmentTransaction 2321 * will have its start triggered. The early triggering may result in faulty or nonexistent 2322 * animations in the postponed transaction. FragmentTransactions that operate only on 2323 * independent containers will not interfere with each other's postponement. 2324 * <p> 2325 * Calling postponeEnterTransition on Fragments with a null View will not postpone the 2326 * transition. Likewise, postponement only works if FragmentTransaction optimizations are 2327 * enabled. 2328 * 2329 * @see Activity#postponeEnterTransition() 2330 * @see FragmentTransaction#setReorderingAllowed(boolean) 2331 */ 2332 public void postponeEnterTransition() { 2333 ensureAnimationInfo().mEnterTransitionPostponed = true; 2334 } 2335 2336 /** 2337 * Begin postponed transitions after {@link #postponeEnterTransition()} was called. 2338 * If postponeEnterTransition() was called, you must call startPostponedEnterTransition() 2339 * or {@link FragmentManager#executePendingTransactions()} to complete the FragmentTransaction. 2340 * If postponement was interrupted with {@link FragmentManager#executePendingTransactions()}, 2341 * before {@code startPostponedEnterTransition()}, animations may not run or may execute 2342 * improperly. 2343 * 2344 * @see Activity#startPostponedEnterTransition() 2345 */ 2346 public void startPostponedEnterTransition() { 2347 if (mFragmentManager == null || mFragmentManager.mHost == null) { 2348 ensureAnimationInfo().mEnterTransitionPostponed = false; 2349 } else if (Looper.myLooper() != mFragmentManager.mHost.getHandler().getLooper()) { 2350 mFragmentManager.mHost.getHandler(). 2351 postAtFrontOfQueue(this::callStartTransitionListener); 2352 } else { 2353 callStartTransitionListener(); 2354 } 2355 } 2356 2357 /** 2358 * Calls the start transition listener. This must be called on the UI thread. 2359 */ 2360 private void callStartTransitionListener() { 2361 final OnStartEnterTransitionListener listener; 2362 if (mAnimationInfo == null) { 2363 listener = null; 2364 } else { 2365 mAnimationInfo.mEnterTransitionPostponed = false; 2366 listener = mAnimationInfo.mStartEnterTransitionListener; 2367 mAnimationInfo.mStartEnterTransitionListener = null; 2368 } 2369 if (listener != null) { 2370 listener.onStartEnterTransition(); 2371 } 2372 } 2373 2374 /** 2375 * Returns true if mAnimationInfo is not null or the transition differs from the default value. 2376 * This is broken out to ensure mAnimationInfo is properly locked when checking. 2377 */ 2378 private boolean shouldChangeTransition(Transition transition, Transition defaultValue) { 2379 if (transition == defaultValue) { 2380 return mAnimationInfo != null; 2381 } 2382 return true; 2383 } 2384 2385 /** 2386 * Print the Fragments's state into the given stream. 2387 * 2388 * @param prefix Text to print at the front of each line. 2389 * @param fd The raw file descriptor that the dump is being sent to. 2390 * @param writer The PrintWriter to which you should dump your state. This will be 2391 * closed for you after you return. 2392 * @param args additional arguments to the dump request. 2393 */ 2394 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 2395 writer.print(prefix); writer.print("mFragmentId=#"); 2396 writer.print(Integer.toHexString(mFragmentId)); 2397 writer.print(" mContainerId=#"); 2398 writer.print(Integer.toHexString(mContainerId)); 2399 writer.print(" mTag="); writer.println(mTag); 2400 writer.print(prefix); writer.print("mState="); writer.print(mState); 2401 writer.print(" mIndex="); writer.print(mIndex); 2402 writer.print(" mWho="); writer.print(mWho); 2403 writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); 2404 writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); 2405 writer.print(" mRemoving="); writer.print(mRemoving); 2406 writer.print(" mFromLayout="); writer.print(mFromLayout); 2407 writer.print(" mInLayout="); writer.println(mInLayout); 2408 writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); 2409 writer.print(" mDetached="); writer.print(mDetached); 2410 writer.print(" mMenuVisible="); writer.print(mMenuVisible); 2411 writer.print(" mHasMenu="); writer.println(mHasMenu); 2412 writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance); 2413 writer.print(" mRetaining="); writer.print(mRetaining); 2414 writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); 2415 if (mFragmentManager != null) { 2416 writer.print(prefix); writer.print("mFragmentManager="); 2417 writer.println(mFragmentManager); 2418 } 2419 if (mHost != null) { 2420 writer.print(prefix); writer.print("mHost="); 2421 writer.println(mHost); 2422 } 2423 if (mParentFragment != null) { 2424 writer.print(prefix); writer.print("mParentFragment="); 2425 writer.println(mParentFragment); 2426 } 2427 if (mArguments != null) { 2428 writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); 2429 } 2430 if (mSavedFragmentState != null) { 2431 writer.print(prefix); writer.print("mSavedFragmentState="); 2432 writer.println(mSavedFragmentState); 2433 } 2434 if (mSavedViewState != null) { 2435 writer.print(prefix); writer.print("mSavedViewState="); 2436 writer.println(mSavedViewState); 2437 } 2438 if (mTarget != null) { 2439 writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); 2440 writer.print(" mTargetRequestCode="); 2441 writer.println(mTargetRequestCode); 2442 } 2443 if (getNextAnim() != 0) { 2444 writer.print(prefix); writer.print("mNextAnim="); writer.println(getNextAnim()); 2445 } 2446 if (mContainer != null) { 2447 writer.print(prefix); writer.print("mContainer="); writer.println(mContainer); 2448 } 2449 if (mView != null) { 2450 writer.print(prefix); writer.print("mView="); writer.println(mView); 2451 } 2452 if (getAnimatingAway() != null) { 2453 writer.print(prefix); writer.print("mAnimatingAway="); 2454 writer.println(getAnimatingAway()); 2455 writer.print(prefix); writer.print("mStateAfterAnimating="); 2456 writer.println(getStateAfterAnimating()); 2457 } 2458 if (mLoaderManager != null) { 2459 writer.print(prefix); writer.println("Loader Manager:"); 2460 mLoaderManager.dump(prefix + " ", fd, writer, args); 2461 } 2462 if (mChildFragmentManager != null) { 2463 writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":"); 2464 mChildFragmentManager.dump(prefix + " ", fd, writer, args); 2465 } 2466 } 2467 2468 Fragment findFragmentByWho(String who) { 2469 if (who.equals(mWho)) { 2470 return this; 2471 } 2472 if (mChildFragmentManager != null) { 2473 return mChildFragmentManager.findFragmentByWho(who); 2474 } 2475 return null; 2476 } 2477 2478 void instantiateChildFragmentManager() { 2479 mChildFragmentManager = new FragmentManagerImpl(); 2480 mChildFragmentManager.attachController(mHost, new FragmentContainer() { 2481 @Override 2482 @Nullable 2483 public <T extends View> T onFindViewById(int id) { 2484 if (mView == null) { 2485 throw new IllegalStateException("Fragment does not have a view"); 2486 } 2487 return mView.findViewById(id); 2488 } 2489 2490 @Override 2491 public boolean onHasView() { 2492 return (mView != null); 2493 } 2494 }, this); 2495 } 2496 2497 void performCreate(Bundle savedInstanceState) { 2498 if (mChildFragmentManager != null) { 2499 mChildFragmentManager.noteStateNotSaved(); 2500 } 2501 mState = CREATED; 2502 mCalled = false; 2503 onCreate(savedInstanceState); 2504 mIsCreated = true; 2505 if (!mCalled) { 2506 throw new SuperNotCalledException("Fragment " + this 2507 + " did not call through to super.onCreate()"); 2508 } 2509 final Context context = getContext(); 2510 final int version = context != null ? context.getApplicationInfo().targetSdkVersion : 0; 2511 if (version < Build.VERSION_CODES.N) { 2512 restoreChildFragmentState(savedInstanceState, false); 2513 } 2514 } 2515 2516 View performCreateView(LayoutInflater inflater, ViewGroup container, 2517 Bundle savedInstanceState) { 2518 if (mChildFragmentManager != null) { 2519 mChildFragmentManager.noteStateNotSaved(); 2520 } 2521 mPerformedCreateView = true; 2522 return onCreateView(inflater, container, savedInstanceState); 2523 } 2524 2525 void performActivityCreated(Bundle savedInstanceState) { 2526 if (mChildFragmentManager != null) { 2527 mChildFragmentManager.noteStateNotSaved(); 2528 } 2529 mState = ACTIVITY_CREATED; 2530 mCalled = false; 2531 onActivityCreated(savedInstanceState); 2532 if (!mCalled) { 2533 throw new SuperNotCalledException("Fragment " + this 2534 + " did not call through to super.onActivityCreated()"); 2535 } 2536 if (mChildFragmentManager != null) { 2537 mChildFragmentManager.dispatchActivityCreated(); 2538 } 2539 } 2540 2541 void performStart() { 2542 if (mChildFragmentManager != null) { 2543 mChildFragmentManager.noteStateNotSaved(); 2544 mChildFragmentManager.execPendingActions(); 2545 } 2546 mState = STARTED; 2547 mCalled = false; 2548 onStart(); 2549 if (!mCalled) { 2550 throw new SuperNotCalledException("Fragment " + this 2551 + " did not call through to super.onStart()"); 2552 } 2553 if (mChildFragmentManager != null) { 2554 mChildFragmentManager.dispatchStart(); 2555 } 2556 if (mLoaderManager != null) { 2557 mLoaderManager.doReportStart(); 2558 } 2559 } 2560 2561 void performResume() { 2562 if (mChildFragmentManager != null) { 2563 mChildFragmentManager.noteStateNotSaved(); 2564 mChildFragmentManager.execPendingActions(); 2565 } 2566 mState = RESUMED; 2567 mCalled = false; 2568 onResume(); 2569 if (!mCalled) { 2570 throw new SuperNotCalledException("Fragment " + this 2571 + " did not call through to super.onResume()"); 2572 } 2573 if (mChildFragmentManager != null) { 2574 mChildFragmentManager.dispatchResume(); 2575 mChildFragmentManager.execPendingActions(); 2576 } 2577 } 2578 2579 void noteStateNotSaved() { 2580 if (mChildFragmentManager != null) { 2581 mChildFragmentManager.noteStateNotSaved(); 2582 } 2583 } 2584 2585 @Deprecated 2586 void performMultiWindowModeChanged(boolean isInMultiWindowMode) { 2587 onMultiWindowModeChanged(isInMultiWindowMode); 2588 if (mChildFragmentManager != null) { 2589 mChildFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode); 2590 } 2591 } 2592 2593 void performMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) { 2594 onMultiWindowModeChanged(isInMultiWindowMode, newConfig); 2595 if (mChildFragmentManager != null) { 2596 mChildFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig); 2597 } 2598 } 2599 2600 @Deprecated 2601 void performPictureInPictureModeChanged(boolean isInPictureInPictureMode) { 2602 onPictureInPictureModeChanged(isInPictureInPictureMode); 2603 if (mChildFragmentManager != null) { 2604 mChildFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode); 2605 } 2606 } 2607 2608 void performPictureInPictureModeChanged(boolean isInPictureInPictureMode, 2609 Configuration newConfig) { 2610 onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); 2611 if (mChildFragmentManager != null) { 2612 mChildFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode, 2613 newConfig); 2614 } 2615 } 2616 2617 void performConfigurationChanged(Configuration newConfig) { 2618 onConfigurationChanged(newConfig); 2619 if (mChildFragmentManager != null) { 2620 mChildFragmentManager.dispatchConfigurationChanged(newConfig); 2621 } 2622 } 2623 2624 void performLowMemory() { 2625 onLowMemory(); 2626 if (mChildFragmentManager != null) { 2627 mChildFragmentManager.dispatchLowMemory(); 2628 } 2629 } 2630 2631 void performTrimMemory(int level) { 2632 onTrimMemory(level); 2633 if (mChildFragmentManager != null) { 2634 mChildFragmentManager.dispatchTrimMemory(level); 2635 } 2636 } 2637 2638 boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) { 2639 boolean show = false; 2640 if (!mHidden) { 2641 if (mHasMenu && mMenuVisible) { 2642 show = true; 2643 onCreateOptionsMenu(menu, inflater); 2644 } 2645 if (mChildFragmentManager != null) { 2646 show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater); 2647 } 2648 } 2649 return show; 2650 } 2651 2652 boolean performPrepareOptionsMenu(Menu menu) { 2653 boolean show = false; 2654 if (!mHidden) { 2655 if (mHasMenu && mMenuVisible) { 2656 show = true; 2657 onPrepareOptionsMenu(menu); 2658 } 2659 if (mChildFragmentManager != null) { 2660 show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu); 2661 } 2662 } 2663 return show; 2664 } 2665 2666 boolean performOptionsItemSelected(MenuItem item) { 2667 if (!mHidden) { 2668 if (mHasMenu && mMenuVisible) { 2669 if (onOptionsItemSelected(item)) { 2670 return true; 2671 } 2672 } 2673 if (mChildFragmentManager != null) { 2674 if (mChildFragmentManager.dispatchOptionsItemSelected(item)) { 2675 return true; 2676 } 2677 } 2678 } 2679 return false; 2680 } 2681 2682 boolean performContextItemSelected(MenuItem item) { 2683 if (!mHidden) { 2684 if (onContextItemSelected(item)) { 2685 return true; 2686 } 2687 if (mChildFragmentManager != null) { 2688 if (mChildFragmentManager.dispatchContextItemSelected(item)) { 2689 return true; 2690 } 2691 } 2692 } 2693 return false; 2694 } 2695 2696 void performOptionsMenuClosed(Menu menu) { 2697 if (!mHidden) { 2698 if (mHasMenu && mMenuVisible) { 2699 onOptionsMenuClosed(menu); 2700 } 2701 if (mChildFragmentManager != null) { 2702 mChildFragmentManager.dispatchOptionsMenuClosed(menu); 2703 } 2704 } 2705 } 2706 2707 void performSaveInstanceState(Bundle outState) { 2708 onSaveInstanceState(outState); 2709 if (mChildFragmentManager != null) { 2710 Parcelable p = mChildFragmentManager.saveAllState(); 2711 if (p != null) { 2712 outState.putParcelable(Activity.FRAGMENTS_TAG, p); 2713 } 2714 } 2715 } 2716 2717 void performPause() { 2718 if (mChildFragmentManager != null) { 2719 mChildFragmentManager.dispatchPause(); 2720 } 2721 mState = STARTED; 2722 mCalled = false; 2723 onPause(); 2724 if (!mCalled) { 2725 throw new SuperNotCalledException("Fragment " + this 2726 + " did not call through to super.onPause()"); 2727 } 2728 } 2729 2730 void performStop() { 2731 if (mChildFragmentManager != null) { 2732 mChildFragmentManager.dispatchStop(); 2733 } 2734 mState = STOPPED; 2735 mCalled = false; 2736 onStop(); 2737 if (!mCalled) { 2738 throw new SuperNotCalledException("Fragment " + this 2739 + " did not call through to super.onStop()"); 2740 } 2741 2742 if (mLoadersStarted) { 2743 mLoadersStarted = false; 2744 if (!mCheckedForLoaderManager) { 2745 mCheckedForLoaderManager = true; 2746 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); 2747 } 2748 if (mLoaderManager != null) { 2749 if (mHost.getRetainLoaders()) { 2750 mLoaderManager.doRetain(); 2751 } else { 2752 mLoaderManager.doStop(); 2753 } 2754 } 2755 } 2756 } 2757 2758 void performDestroyView() { 2759 if (mChildFragmentManager != null) { 2760 mChildFragmentManager.dispatchDestroyView(); 2761 } 2762 mState = CREATED; 2763 mCalled = false; 2764 onDestroyView(); 2765 if (!mCalled) { 2766 throw new SuperNotCalledException("Fragment " + this 2767 + " did not call through to super.onDestroyView()"); 2768 } 2769 if (mLoaderManager != null) { 2770 mLoaderManager.doReportNextStart(); 2771 } 2772 mPerformedCreateView = false; 2773 } 2774 2775 void performDestroy() { 2776 if (mChildFragmentManager != null) { 2777 mChildFragmentManager.dispatchDestroy(); 2778 } 2779 mState = INITIALIZING; 2780 mCalled = false; 2781 mIsCreated = false; 2782 onDestroy(); 2783 if (!mCalled) { 2784 throw new SuperNotCalledException("Fragment " + this 2785 + " did not call through to super.onDestroy()"); 2786 } 2787 mChildFragmentManager = null; 2788 } 2789 2790 void performDetach() { 2791 mCalled = false; 2792 onDetach(); 2793 mLayoutInflater = null; 2794 if (!mCalled) { 2795 throw new SuperNotCalledException("Fragment " + this 2796 + " did not call through to super.onDetach()"); 2797 } 2798 2799 // Destroy the child FragmentManager if we still have it here. 2800 // We won't unless we're retaining our instance and if we do, 2801 // our child FragmentManager instance state will have already been saved. 2802 if (mChildFragmentManager != null) { 2803 if (!mRetaining) { 2804 throw new IllegalStateException("Child FragmentManager of " + this + " was not " 2805 + " destroyed and this fragment is not retaining instance"); 2806 } 2807 mChildFragmentManager.dispatchDestroy(); 2808 mChildFragmentManager = null; 2809 } 2810 } 2811 2812 void setOnStartEnterTransitionListener(OnStartEnterTransitionListener listener) { 2813 ensureAnimationInfo(); 2814 if (listener == mAnimationInfo.mStartEnterTransitionListener) { 2815 return; 2816 } 2817 if (listener != null && mAnimationInfo.mStartEnterTransitionListener != null) { 2818 throw new IllegalStateException("Trying to set a replacement " + 2819 "startPostponedEnterTransition on " + this); 2820 } 2821 if (mAnimationInfo.mEnterTransitionPostponed) { 2822 mAnimationInfo.mStartEnterTransitionListener = listener; 2823 } 2824 if (listener != null) { 2825 listener.startListening(); 2826 } 2827 } 2828 2829 private static Transition loadTransition(Context context, TypedArray typedArray, 2830 Transition currentValue, Transition defaultValue, int id) { 2831 if (currentValue != defaultValue) { 2832 return currentValue; 2833 } 2834 int transitionId = typedArray.getResourceId(id, 0); 2835 Transition transition = defaultValue; 2836 if (transitionId != 0 && transitionId != com.android.internal.R.transition.no_transition) { 2837 TransitionInflater inflater = TransitionInflater.from(context); 2838 transition = inflater.inflateTransition(transitionId); 2839 if (transition instanceof TransitionSet && 2840 ((TransitionSet)transition).getTransitionCount() == 0) { 2841 transition = null; 2842 } 2843 } 2844 return transition; 2845 } 2846 2847 private AnimationInfo ensureAnimationInfo() { 2848 if (mAnimationInfo == null) { 2849 mAnimationInfo = new AnimationInfo(); 2850 } 2851 return mAnimationInfo; 2852 } 2853 2854 int getNextAnim() { 2855 if (mAnimationInfo == null) { 2856 return 0; 2857 } 2858 return mAnimationInfo.mNextAnim; 2859 } 2860 2861 void setNextAnim(int animResourceId) { 2862 if (mAnimationInfo == null && animResourceId == 0) { 2863 return; // no change! 2864 } 2865 ensureAnimationInfo().mNextAnim = animResourceId; 2866 } 2867 2868 int getNextTransition() { 2869 if (mAnimationInfo == null) { 2870 return 0; 2871 } 2872 return mAnimationInfo.mNextTransition; 2873 } 2874 2875 void setNextTransition(int nextTransition, int nextTransitionStyle) { 2876 if (mAnimationInfo == null && nextTransition == 0 && nextTransitionStyle == 0) { 2877 return; // no change! 2878 } 2879 ensureAnimationInfo(); 2880 mAnimationInfo.mNextTransition = nextTransition; 2881 mAnimationInfo.mNextTransitionStyle = nextTransitionStyle; 2882 } 2883 2884 int getNextTransitionStyle() { 2885 if (mAnimationInfo == null) { 2886 return 0; 2887 } 2888 return mAnimationInfo.mNextTransitionStyle; 2889 } 2890 2891 SharedElementCallback getEnterTransitionCallback() { 2892 if (mAnimationInfo == null) { 2893 return SharedElementCallback.NULL_CALLBACK; 2894 } 2895 return mAnimationInfo.mEnterTransitionCallback; 2896 } 2897 2898 SharedElementCallback getExitTransitionCallback() { 2899 if (mAnimationInfo == null) { 2900 return SharedElementCallback.NULL_CALLBACK; 2901 } 2902 return mAnimationInfo.mExitTransitionCallback; 2903 } 2904 2905 Animator getAnimatingAway() { 2906 if (mAnimationInfo == null) { 2907 return null; 2908 } 2909 return mAnimationInfo.mAnimatingAway; 2910 } 2911 2912 void setAnimatingAway(Animator animator) { 2913 ensureAnimationInfo().mAnimatingAway = animator; 2914 } 2915 2916 int getStateAfterAnimating() { 2917 if (mAnimationInfo == null) { 2918 return 0; 2919 } 2920 return mAnimationInfo.mStateAfterAnimating; 2921 } 2922 2923 void setStateAfterAnimating(int state) { 2924 ensureAnimationInfo().mStateAfterAnimating = state; 2925 } 2926 2927 boolean isPostponed() { 2928 if (mAnimationInfo == null) { 2929 return false; 2930 } 2931 return mAnimationInfo.mEnterTransitionPostponed; 2932 } 2933 2934 boolean isHideReplaced() { 2935 if (mAnimationInfo == null) { 2936 return false; 2937 } 2938 return mAnimationInfo.mIsHideReplaced; 2939 } 2940 2941 void setHideReplaced(boolean replaced) { 2942 ensureAnimationInfo().mIsHideReplaced = replaced; 2943 } 2944 2945 /** 2946 * Used internally to be notified when {@link #startPostponedEnterTransition()} has 2947 * been called. This listener will only be called once and then be removed from the 2948 * listeners. 2949 */ 2950 interface OnStartEnterTransitionListener { 2951 void onStartEnterTransition(); 2952 void startListening(); 2953 } 2954 2955 /** 2956 * Contains all the animation and transition information for a fragment. This will only 2957 * be instantiated for Fragments that have Views. 2958 */ 2959 static class AnimationInfo { 2960 // Non-null if the fragment's view hierarchy is currently animating away, 2961 // meaning we need to wait a bit on completely destroying it. This is the 2962 // animation that is running. 2963 Animator mAnimatingAway; 2964 2965 // If mAnimatingAway != null, this is the state we should move to once the 2966 // animation is done. 2967 int mStateAfterAnimating; 2968 2969 // If app has requested a specific animation, this is the one to use. 2970 int mNextAnim; 2971 2972 // If app has requested a specific transition, this is the one to use. 2973 int mNextTransition; 2974 2975 // If app has requested a specific transition style, this is the one to use. 2976 int mNextTransitionStyle; 2977 2978 private Transition mEnterTransition = null; 2979 private Transition mReturnTransition = USE_DEFAULT_TRANSITION; 2980 private Transition mExitTransition = null; 2981 private Transition mReenterTransition = USE_DEFAULT_TRANSITION; 2982 private Transition mSharedElementEnterTransition = null; 2983 private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION; 2984 private Boolean mAllowReturnTransitionOverlap; 2985 private Boolean mAllowEnterTransitionOverlap; 2986 2987 SharedElementCallback mEnterTransitionCallback = SharedElementCallback.NULL_CALLBACK; 2988 SharedElementCallback mExitTransitionCallback = SharedElementCallback.NULL_CALLBACK; 2989 2990 // True when postponeEnterTransition has been called and startPostponeEnterTransition 2991 // hasn't been called yet. 2992 boolean mEnterTransitionPostponed; 2993 2994 // Listener to wait for startPostponeEnterTransition. After being called, it will 2995 // be set to null 2996 OnStartEnterTransitionListener mStartEnterTransitionListener; 2997 2998 // True if the View was hidden, but the transition is handling the hide 2999 boolean mIsHideReplaced; 3000 } 3001 } 3002