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.os.Parcel; 20 import android.os.Parcelable; 21 import android.text.TextUtils; 22 import android.util.Log; 23 24 import java.io.FileDescriptor; 25 import java.io.PrintWriter; 26 import java.util.ArrayList; 27 28 final class BackStackState implements Parcelable { 29 final int[] mOps; 30 final int mTransition; 31 final int mTransitionStyle; 32 final String mName; 33 final int mIndex; 34 final int mBreadCrumbTitleRes; 35 final CharSequence mBreadCrumbTitleText; 36 final int mBreadCrumbShortTitleRes; 37 final CharSequence mBreadCrumbShortTitleText; 38 39 public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) { 40 int numRemoved = 0; 41 BackStackRecord.Op op = bse.mHead; 42 while (op != null) { 43 if (op.removed != null) numRemoved += op.removed.size(); 44 op = op.next; 45 } 46 mOps = new int[bse.mNumOp*7 + numRemoved]; 47 48 if (!bse.mAddToBackStack) { 49 throw new IllegalStateException("Not on back stack"); 50 } 51 52 op = bse.mHead; 53 int pos = 0; 54 while (op != null) { 55 mOps[pos++] = op.cmd; 56 mOps[pos++] = op.fragment != null ? op.fragment.mIndex : -1; 57 mOps[pos++] = op.enterAnim; 58 mOps[pos++] = op.exitAnim; 59 mOps[pos++] = op.popEnterAnim; 60 mOps[pos++] = op.popExitAnim; 61 if (op.removed != null) { 62 final int N = op.removed.size(); 63 mOps[pos++] = N; 64 for (int i=0; i<N; i++) { 65 mOps[pos++] = op.removed.get(i).mIndex; 66 } 67 } else { 68 mOps[pos++] = 0; 69 } 70 op = op.next; 71 } 72 mTransition = bse.mTransition; 73 mTransitionStyle = bse.mTransitionStyle; 74 mName = bse.mName; 75 mIndex = bse.mIndex; 76 mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes; 77 mBreadCrumbTitleText = bse.mBreadCrumbTitleText; 78 mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes; 79 mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText; 80 } 81 82 public BackStackState(Parcel in) { 83 mOps = in.createIntArray(); 84 mTransition = in.readInt(); 85 mTransitionStyle = in.readInt(); 86 mName = in.readString(); 87 mIndex = in.readInt(); 88 mBreadCrumbTitleRes = in.readInt(); 89 mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 90 mBreadCrumbShortTitleRes = in.readInt(); 91 mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 92 } 93 94 public BackStackRecord instantiate(FragmentManagerImpl fm) { 95 BackStackRecord bse = new BackStackRecord(fm); 96 int pos = 0; 97 while (pos < mOps.length) { 98 BackStackRecord.Op op = new BackStackRecord.Op(); 99 op.cmd = mOps[pos++]; 100 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 101 "BSE " + bse + " set base fragment #" + mOps[pos]); 102 int findex = mOps[pos++]; 103 if (findex >= 0) { 104 Fragment f = fm.mActive.get(findex); 105 op.fragment = f; 106 } else { 107 op.fragment = null; 108 } 109 op.enterAnim = mOps[pos++]; 110 op.exitAnim = mOps[pos++]; 111 op.popEnterAnim = mOps[pos++]; 112 op.popExitAnim = mOps[pos++]; 113 final int N = mOps[pos++]; 114 if (N > 0) { 115 op.removed = new ArrayList<Fragment>(N); 116 for (int i=0; i<N; i++) { 117 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 118 "BSE " + bse + " set remove fragment #" + mOps[pos]); 119 Fragment r = fm.mActive.get(mOps[pos++]); 120 op.removed.add(r); 121 } 122 } 123 bse.addOp(op); 124 } 125 bse.mTransition = mTransition; 126 bse.mTransitionStyle = mTransitionStyle; 127 bse.mName = mName; 128 bse.mIndex = mIndex; 129 bse.mAddToBackStack = true; 130 bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes; 131 bse.mBreadCrumbTitleText = mBreadCrumbTitleText; 132 bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes; 133 bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText; 134 bse.bumpBackStackNesting(1); 135 return bse; 136 } 137 138 public int describeContents() { 139 return 0; 140 } 141 142 public void writeToParcel(Parcel dest, int flags) { 143 dest.writeIntArray(mOps); 144 dest.writeInt(mTransition); 145 dest.writeInt(mTransitionStyle); 146 dest.writeString(mName); 147 dest.writeInt(mIndex); 148 dest.writeInt(mBreadCrumbTitleRes); 149 TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0); 150 dest.writeInt(mBreadCrumbShortTitleRes); 151 TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0); 152 } 153 154 public static final Parcelable.Creator<BackStackState> CREATOR 155 = new Parcelable.Creator<BackStackState>() { 156 public BackStackState createFromParcel(Parcel in) { 157 return new BackStackState(in); 158 } 159 160 public BackStackState[] newArray(int size) { 161 return new BackStackState[size]; 162 } 163 }; 164 } 165 166 /** 167 * @hide Entry of an operation on the fragment back stack. 168 */ 169 final class BackStackRecord extends FragmentTransaction implements 170 FragmentManager.BackStackEntry, Runnable { 171 static final String TAG = "BackStackEntry"; 172 173 final FragmentManagerImpl mManager; 174 175 static final int OP_NULL = 0; 176 static final int OP_ADD = 1; 177 static final int OP_REPLACE = 2; 178 static final int OP_REMOVE = 3; 179 static final int OP_HIDE = 4; 180 static final int OP_SHOW = 5; 181 static final int OP_DETACH = 6; 182 static final int OP_ATTACH = 7; 183 184 static final class Op { 185 Op next; 186 Op prev; 187 int cmd; 188 Fragment fragment; 189 int enterAnim; 190 int exitAnim; 191 int popEnterAnim; 192 int popExitAnim; 193 ArrayList<Fragment> removed; 194 } 195 196 Op mHead; 197 Op mTail; 198 int mNumOp; 199 int mEnterAnim; 200 int mExitAnim; 201 int mPopEnterAnim; 202 int mPopExitAnim; 203 int mTransition; 204 int mTransitionStyle; 205 boolean mAddToBackStack; 206 boolean mAllowAddToBackStack = true; 207 String mName; 208 boolean mCommitted; 209 int mIndex; 210 211 int mBreadCrumbTitleRes; 212 CharSequence mBreadCrumbTitleText; 213 int mBreadCrumbShortTitleRes; 214 CharSequence mBreadCrumbShortTitleText; 215 216 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 217 writer.print(prefix); writer.print("mName="); writer.print(mName); 218 writer.print(" mIndex="); writer.print(mIndex); 219 writer.print(" mCommitted="); writer.println(mCommitted); 220 if (mTransition != FragmentTransaction.TRANSIT_NONE) { 221 writer.print(prefix); writer.print("mTransition=#"); 222 writer.print(Integer.toHexString(mTransition)); 223 writer.print(" mTransitionStyle=#"); 224 writer.println(Integer.toHexString(mTransitionStyle)); 225 } 226 if (mEnterAnim != 0 || mExitAnim !=0) { 227 writer.print(prefix); writer.print("mEnterAnim=#"); 228 writer.print(Integer.toHexString(mEnterAnim)); 229 writer.print(" mExitAnim=#"); 230 writer.println(Integer.toHexString(mExitAnim)); 231 } 232 if (mPopEnterAnim != 0 || mPopExitAnim !=0) { 233 writer.print(prefix); writer.print("mPopEnterAnim=#"); 234 writer.print(Integer.toHexString(mPopEnterAnim)); 235 writer.print(" mPopExitAnim=#"); 236 writer.println(Integer.toHexString(mPopExitAnim)); 237 } 238 if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) { 239 writer.print(prefix); writer.print("mBreadCrumbTitleRes=#"); 240 writer.print(Integer.toHexString(mBreadCrumbTitleRes)); 241 writer.print(" mBreadCrumbTitleText="); 242 writer.println(mBreadCrumbTitleText); 243 } 244 if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) { 245 writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#"); 246 writer.print(Integer.toHexString(mBreadCrumbShortTitleRes)); 247 writer.print(" mBreadCrumbShortTitleText="); 248 writer.println(mBreadCrumbShortTitleText); 249 } 250 251 if (mHead != null) { 252 writer.print(prefix); writer.println("Operations:"); 253 String innerPrefix = prefix + " "; 254 Op op = mHead; 255 int num = 0; 256 while (op != null) { 257 writer.print(prefix); writer.print(" Op #"); writer.print(num); 258 writer.println(":"); 259 writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd); 260 writer.print(" fragment="); writer.println(op.fragment); 261 if (op.enterAnim != 0 || op.exitAnim != 0) { 262 writer.print(prefix); writer.print("enterAnim=#"); 263 writer.print(Integer.toHexString(op.enterAnim)); 264 writer.print(" exitAnim=#"); 265 writer.println(Integer.toHexString(op.exitAnim)); 266 } 267 if (op.popEnterAnim != 0 || op.popExitAnim != 0) { 268 writer.print(prefix); writer.print("popEnterAnim=#"); 269 writer.print(Integer.toHexString(op.popEnterAnim)); 270 writer.print(" popExitAnim=#"); 271 writer.println(Integer.toHexString(op.popExitAnim)); 272 } 273 if (op.removed != null && op.removed.size() > 0) { 274 for (int i=0; i<op.removed.size(); i++) { 275 writer.print(innerPrefix); 276 if (op.removed.size() == 1) { 277 writer.print("Removed: "); 278 } else { 279 writer.println("Removed:"); 280 writer.print(innerPrefix); writer.print(" #"); writer.print(num); 281 writer.print(": "); 282 } 283 writer.println(op.removed.get(i)); 284 } 285 } 286 op = op.next; 287 } 288 } 289 } 290 291 public BackStackRecord(FragmentManagerImpl manager) { 292 mManager = manager; 293 } 294 295 public int getId() { 296 return mIndex; 297 } 298 299 public int getBreadCrumbTitleRes() { 300 return mBreadCrumbTitleRes; 301 } 302 303 public int getBreadCrumbShortTitleRes() { 304 return mBreadCrumbShortTitleRes; 305 } 306 307 public CharSequence getBreadCrumbTitle() { 308 if (mBreadCrumbTitleRes != 0) { 309 return mManager.mActivity.getText(mBreadCrumbTitleRes); 310 } 311 return mBreadCrumbTitleText; 312 } 313 314 public CharSequence getBreadCrumbShortTitle() { 315 if (mBreadCrumbShortTitleRes != 0) { 316 return mManager.mActivity.getText(mBreadCrumbShortTitleRes); 317 } 318 return mBreadCrumbShortTitleText; 319 } 320 321 void addOp(Op op) { 322 if (mHead == null) { 323 mHead = mTail = op; 324 } else { 325 op.prev = mTail; 326 mTail.next = op; 327 mTail = op; 328 } 329 op.enterAnim = mEnterAnim; 330 op.exitAnim = mExitAnim; 331 op.popEnterAnim = mPopEnterAnim; 332 op.popExitAnim = mPopExitAnim; 333 mNumOp++; 334 } 335 336 public FragmentTransaction add(Fragment fragment, String tag) { 337 doAddOp(0, fragment, tag, OP_ADD); 338 return this; 339 } 340 341 public FragmentTransaction add(int containerViewId, Fragment fragment) { 342 doAddOp(containerViewId, fragment, null, OP_ADD); 343 return this; 344 } 345 346 public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) { 347 doAddOp(containerViewId, fragment, tag, OP_ADD); 348 return this; 349 } 350 351 private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { 352 fragment.mFragmentManager = mManager; 353 354 if (tag != null) { 355 if (fragment.mTag != null && !tag.equals(fragment.mTag)) { 356 throw new IllegalStateException("Can't change tag of fragment " 357 + fragment + ": was " + fragment.mTag 358 + " now " + tag); 359 } 360 fragment.mTag = tag; 361 } 362 363 if (containerViewId != 0) { 364 if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) { 365 throw new IllegalStateException("Can't change container ID of fragment " 366 + fragment + ": was " + fragment.mFragmentId 367 + " now " + containerViewId); 368 } 369 fragment.mContainerId = fragment.mFragmentId = containerViewId; 370 } 371 372 Op op = new Op(); 373 op.cmd = opcmd; 374 op.fragment = fragment; 375 addOp(op); 376 } 377 378 public FragmentTransaction replace(int containerViewId, Fragment fragment) { 379 return replace(containerViewId, fragment, null); 380 } 381 382 public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) { 383 if (containerViewId == 0) { 384 throw new IllegalArgumentException("Must use non-zero containerViewId"); 385 } 386 387 doAddOp(containerViewId, fragment, tag, OP_REPLACE); 388 return this; 389 } 390 391 public FragmentTransaction remove(Fragment fragment) { 392 Op op = new Op(); 393 op.cmd = OP_REMOVE; 394 op.fragment = fragment; 395 addOp(op); 396 397 return this; 398 } 399 400 public FragmentTransaction hide(Fragment fragment) { 401 Op op = new Op(); 402 op.cmd = OP_HIDE; 403 op.fragment = fragment; 404 addOp(op); 405 406 return this; 407 } 408 409 public FragmentTransaction show(Fragment fragment) { 410 Op op = new Op(); 411 op.cmd = OP_SHOW; 412 op.fragment = fragment; 413 addOp(op); 414 415 return this; 416 } 417 418 public FragmentTransaction detach(Fragment fragment) { 419 Op op = new Op(); 420 op.cmd = OP_DETACH; 421 op.fragment = fragment; 422 addOp(op); 423 424 return this; 425 } 426 427 public FragmentTransaction attach(Fragment fragment) { 428 Op op = new Op(); 429 op.cmd = OP_ATTACH; 430 op.fragment = fragment; 431 addOp(op); 432 433 return this; 434 } 435 436 public FragmentTransaction setCustomAnimations(int enter, int exit) { 437 return setCustomAnimations(enter, exit, 0, 0); 438 } 439 440 public FragmentTransaction setCustomAnimations(int enter, int exit, 441 int popEnter, int popExit) { 442 mEnterAnim = enter; 443 mExitAnim = exit; 444 mPopEnterAnim = popEnter; 445 mPopExitAnim = popExit; 446 return this; 447 } 448 449 public FragmentTransaction setTransition(int transition) { 450 mTransition = transition; 451 return this; 452 } 453 454 public FragmentTransaction setTransitionStyle(int styleRes) { 455 mTransitionStyle = styleRes; 456 return this; 457 } 458 459 public FragmentTransaction addToBackStack(String name) { 460 if (!mAllowAddToBackStack) { 461 throw new IllegalStateException( 462 "This FragmentTransaction is not allowed to be added to the back stack."); 463 } 464 mAddToBackStack = true; 465 mName = name; 466 return this; 467 } 468 469 public boolean isAddToBackStackAllowed() { 470 return mAllowAddToBackStack; 471 } 472 473 public FragmentTransaction disallowAddToBackStack() { 474 if (mAddToBackStack) { 475 throw new IllegalStateException( 476 "This transaction is already being added to the back stack"); 477 } 478 mAllowAddToBackStack = false; 479 return this; 480 } 481 482 public FragmentTransaction setBreadCrumbTitle(int res) { 483 mBreadCrumbTitleRes = res; 484 mBreadCrumbTitleText = null; 485 return this; 486 } 487 488 public FragmentTransaction setBreadCrumbTitle(CharSequence text) { 489 mBreadCrumbTitleRes = 0; 490 mBreadCrumbTitleText = text; 491 return this; 492 } 493 494 public FragmentTransaction setBreadCrumbShortTitle(int res) { 495 mBreadCrumbShortTitleRes = res; 496 mBreadCrumbShortTitleText = null; 497 return this; 498 } 499 500 public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) { 501 mBreadCrumbShortTitleRes = 0; 502 mBreadCrumbShortTitleText = text; 503 return this; 504 } 505 506 void bumpBackStackNesting(int amt) { 507 if (!mAddToBackStack) { 508 return; 509 } 510 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting in " + this 511 + " by " + amt); 512 Op op = mHead; 513 while (op != null) { 514 if (op.fragment != null) { 515 op.fragment.mBackStackNesting += amt; 516 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " 517 + op.fragment + " to " + op.fragment.mBackStackNesting); 518 } 519 if (op.removed != null) { 520 for (int i=op.removed.size()-1; i>=0; i--) { 521 Fragment r = op.removed.get(i); 522 r.mBackStackNesting += amt; 523 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " 524 + r + " to " + r.mBackStackNesting); 525 } 526 } 527 op = op.next; 528 } 529 } 530 531 public int commit() { 532 return commitInternal(false); 533 } 534 535 public int commitAllowingStateLoss() { 536 return commitInternal(true); 537 } 538 539 int commitInternal(boolean allowStateLoss) { 540 if (mCommitted) throw new IllegalStateException("commit already called"); 541 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this); 542 mCommitted = true; 543 if (mAddToBackStack) { 544 mIndex = mManager.allocBackStackIndex(this); 545 } else { 546 mIndex = -1; 547 } 548 mManager.enqueueAction(this, allowStateLoss); 549 return mIndex; 550 } 551 552 public void run() { 553 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); 554 555 if (mAddToBackStack) { 556 if (mIndex < 0) { 557 throw new IllegalStateException("addToBackStack() called after commit()"); 558 } 559 } 560 561 bumpBackStackNesting(1); 562 563 Op op = mHead; 564 while (op != null) { 565 switch (op.cmd) { 566 case OP_ADD: { 567 Fragment f = op.fragment; 568 f.mNextAnim = op.enterAnim; 569 mManager.addFragment(f, false); 570 } break; 571 case OP_REPLACE: { 572 Fragment f = op.fragment; 573 if (mManager.mAdded != null) { 574 for (int i=0; i<mManager.mAdded.size(); i++) { 575 Fragment old = mManager.mAdded.get(i); 576 if (FragmentManagerImpl.DEBUG) Log.v(TAG, 577 "OP_REPLACE: adding=" + f + " old=" + old); 578 if (f == null || old.mContainerId == f.mContainerId) { 579 if (old == f) { 580 op.fragment = f = null; 581 } else { 582 if (op.removed == null) { 583 op.removed = new ArrayList<Fragment>(); 584 } 585 op.removed.add(old); 586 old.mNextAnim = op.exitAnim; 587 if (mAddToBackStack) { 588 old.mBackStackNesting += 1; 589 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " 590 + old + " to " + old.mBackStackNesting); 591 } 592 mManager.removeFragment(old, mTransition, mTransitionStyle); 593 } 594 } 595 } 596 } 597 if (f != null) { 598 f.mNextAnim = op.enterAnim; 599 mManager.addFragment(f, false); 600 } 601 } break; 602 case OP_REMOVE: { 603 Fragment f = op.fragment; 604 f.mNextAnim = op.exitAnim; 605 mManager.removeFragment(f, mTransition, mTransitionStyle); 606 } break; 607 case OP_HIDE: { 608 Fragment f = op.fragment; 609 f.mNextAnim = op.exitAnim; 610 mManager.hideFragment(f, mTransition, mTransitionStyle); 611 } break; 612 case OP_SHOW: { 613 Fragment f = op.fragment; 614 f.mNextAnim = op.enterAnim; 615 mManager.showFragment(f, mTransition, mTransitionStyle); 616 } break; 617 case OP_DETACH: { 618 Fragment f = op.fragment; 619 f.mNextAnim = op.exitAnim; 620 mManager.detachFragment(f, mTransition, mTransitionStyle); 621 } break; 622 case OP_ATTACH: { 623 Fragment f = op.fragment; 624 f.mNextAnim = op.enterAnim; 625 mManager.attachFragment(f, mTransition, mTransitionStyle); 626 } break; 627 default: { 628 throw new IllegalArgumentException("Unknown cmd: " + op.cmd); 629 } 630 } 631 632 op = op.next; 633 } 634 635 mManager.moveToState(mManager.mCurState, mTransition, 636 mTransitionStyle, true); 637 638 if (mAddToBackStack) { 639 mManager.addBackStackState(this); 640 } 641 } 642 643 public void popFromBackStack(boolean doStateMove) { 644 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this); 645 646 bumpBackStackNesting(-1); 647 648 Op op = mTail; 649 while (op != null) { 650 switch (op.cmd) { 651 case OP_ADD: { 652 Fragment f = op.fragment; 653 f.mNextAnim = op.popExitAnim; 654 mManager.removeFragment(f, 655 FragmentManagerImpl.reverseTransit(mTransition), 656 mTransitionStyle); 657 } break; 658 case OP_REPLACE: { 659 Fragment f = op.fragment; 660 if (f != null) { 661 f.mNextAnim = op.popExitAnim; 662 mManager.removeFragment(f, 663 FragmentManagerImpl.reverseTransit(mTransition), 664 mTransitionStyle); 665 } 666 if (op.removed != null) { 667 for (int i=0; i<op.removed.size(); i++) { 668 Fragment old = op.removed.get(i); 669 old.mNextAnim = op.popEnterAnim; 670 mManager.addFragment(old, false); 671 } 672 } 673 } break; 674 case OP_REMOVE: { 675 Fragment f = op.fragment; 676 f.mNextAnim = op.popEnterAnim; 677 mManager.addFragment(f, false); 678 } break; 679 case OP_HIDE: { 680 Fragment f = op.fragment; 681 f.mNextAnim = op.popEnterAnim; 682 mManager.showFragment(f, 683 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 684 } break; 685 case OP_SHOW: { 686 Fragment f = op.fragment; 687 f.mNextAnim = op.popExitAnim; 688 mManager.hideFragment(f, 689 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 690 } break; 691 case OP_DETACH: { 692 Fragment f = op.fragment; 693 f.mNextAnim = op.popEnterAnim; 694 mManager.attachFragment(f, 695 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 696 } break; 697 case OP_ATTACH: { 698 Fragment f = op.fragment; 699 f.mNextAnim = op.popExitAnim; 700 mManager.detachFragment(f, 701 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 702 } break; 703 default: { 704 throw new IllegalArgumentException("Unknown cmd: " + op.cmd); 705 } 706 } 707 708 op = op.prev; 709 } 710 711 if (doStateMove) { 712 mManager.moveToState(mManager.mCurState, 713 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); 714 } 715 716 if (mIndex >= 0) { 717 mManager.freeBackStackIndex(mIndex); 718 mIndex = -1; 719 } 720 } 721 722 public String getName() { 723 return mName; 724 } 725 726 public int getTransition() { 727 return mTransition; 728 } 729 730 public int getTransitionStyle() { 731 return mTransitionStyle; 732 } 733 734 public boolean isEmpty() { 735 return mNumOp == 0; 736 } 737 } 738