diff options
| author | 2017-01-17 17:48:33 +0000 | |
|---|---|---|
| committer | 2017-01-17 17:48:38 +0000 | |
| commit | ce29c76a1baac71b0c413ca9b4c20c9addb725a9 (patch) | |
| tree | 3c8bcefbcacdb36add52700847274d662a0005d6 | |
| parent | 1a6cd84d64cce1263958d827f8c7c90c531e5de6 (diff) | |
| parent | c21dfd9b5cf35f97e129e08d65c37913ee47f88f (diff) | |
Merge "Fix focus problems when using optimized fragment transactions."
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 55 | ||||
| -rw-r--r-- | core/java/android/app/FragmentTransition.java | 5 |
2 files changed, 44 insertions, 16 deletions
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 92ba4408b5ce..6fb6b9445211 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -31,6 +31,7 @@ import android.os.Debug; import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; +import android.util.ArraySet; import android.util.AttributeSet; import android.util.DebugUtils; import android.util.Log; @@ -1245,11 +1246,13 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate dispatchOnFragmentViewDestroyed(f, false); if (f.mView != null && f.mContainer != null) { Animator anim = null; - if (mCurState > Fragment.INITIALIZING && !mDestroyed && - f.mView.getVisibility() == View.VISIBLE) { + if (mCurState > Fragment.INITIALIZING && !mDestroyed + && f.mView.getVisibility() == View.VISIBLE + && f.mView.getTransitionAlpha() > 0) { anim = loadAnimator(f, transit, false, transitionStyle); } + f.mView.setTransitionAlpha(1f); if (anim != null) { final ViewGroup container = f.mContainer; final View view = f.mView; @@ -1439,7 +1442,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } if (f.mIsNewlyAdded && f.mContainer != null) { // Make it visible and run the animations - f.mView.setVisibility(View.VISIBLE); + f.mView.setTransitionAlpha(1f); f.mIsNewlyAdded = false; // run animations: Animator anim = loadAnimator(f, f.getNextTransition(), true, f.getNextTransitionStyle()); @@ -2038,9 +2041,11 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate int postponeIndex = endIndex; if (allowOptimization) { - moveFragmentsToInvisible(); + ArraySet<Fragment> addedFragments = new ArraySet<>(); + addAddedFragments(addedFragments); postponeIndex = postponePostponableTransactions(records, isRecordPop, - startIndex, endIndex); + startIndex, endIndex, addedFragments); + makeRemovedFragmentsInvisible(addedFragments); } if (postponeIndex != startIndex && allowOptimization) { @@ -2065,6 +2070,24 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } /** + * Any fragments that were removed because they have been postponed should have their views + * made invisible by setting their transition alpha to 0. + * + * @param fragments The fragments that were added during operation execution. Only the ones + * that are no longer added will have their transition alpha changed. + */ + private void makeRemovedFragmentsInvisible(ArraySet<Fragment> fragments) { + final int numAdded = fragments.size(); + for (int i = 0; i < numAdded; i++) { + final Fragment fragment = fragments.valueAt(i); + if (!fragment.mAdded) { + final View view = fragment.getView(); + view.setTransitionAlpha(0f); + } + } + } + + /** * Examine all transactions and determine which ones are marked as postponed. Those will * have their operations rolled back and moved to the end of the record list (up to endIndex). * It will also add the postponed transaction to the queue. @@ -2077,7 +2100,8 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate * postponed. */ private int postponePostponableTransactions(ArrayList<BackStackRecord> records, - ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) { + ArrayList<Boolean> isRecordPop, int startIndex, int endIndex, + ArraySet<Fragment> added) { int postponeIndex = endIndex; for (int i = endIndex - 1; i >= startIndex; i--) { final BackStackRecord record = records.get(i); @@ -2108,7 +2132,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } // different views may be visible now - moveFragmentsToInvisible(); + addAddedFragments(added); } } return postponeIndex; @@ -2141,14 +2165,16 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } if (moveToState) { moveToState(mCurState, true); - } else if (mActive != null) { + } + + if (mActive != null) { final int numActive = mActive.size(); for (int i = 0; i < numActive; i++) { // Allow added fragments to be removed during the pop since we aren't going // to move them to the final state with moveToState(mCurState). Fragment fragment = mActive.get(i); - if (fragment.mView != null && fragment.mIsNewlyAdded && - record.interactsWith(fragment.mContainerId)) { + if (fragment != null && fragment.mView != null && fragment.mIsNewlyAdded + && record.interactsWith(fragment.mContainerId)) { fragment.mIsNewlyAdded = false; } } @@ -2213,10 +2239,11 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate /** * Ensure that fragments that are added are moved to at least the CREATED state. - * Any newly-added Views are made INVISIBLE so that the Transaction can be postponed - * with {@link Fragment#postponeEnterTransition()}. + * Any newly-added Views are inserted into {@code added} so that the Transaction can be + * postponed with {@link Fragment#postponeEnterTransition()}. They will later be made + * invisible by changing their transitionAlpha to 0 if they have been removed when postponed. */ - private void moveFragmentsToInvisible() { + private void addAddedFragments(ArraySet<Fragment> added) { if (mCurState < Fragment.CREATED) { return; } @@ -2228,7 +2255,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate if (fragment.mState < state) { moveToState(fragment, state, fragment.getNextAnim(), fragment.getNextTransition(), false); if (fragment.mView != null && !fragment.mHidden && fragment.mIsNewlyAdded) { - fragment.mView.setVisibility(View.INVISIBLE); + added.add(fragment); } } } diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java index 33244481c289..6d57cd438a6f 100644 --- a/core/java/android/app/FragmentTransition.java +++ b/core/java/android/app/FragmentTransition.java @@ -1266,8 +1266,9 @@ class FragmentTransition { case BackStackRecord.OP_REMOVE: case BackStackRecord.OP_DETACH: if (isOptimizedTransaction) { - setFirstOut = !fragment.mAdded && fragment.mView != null && - fragment.mView.getVisibility() == View.VISIBLE; + setFirstOut = !fragment.mAdded && fragment.mView != null + && fragment.mView.getVisibility() == View.VISIBLE + && fragment.mView.getTransitionAlpha() > 0; } else { setFirstOut = fragment.mAdded && !fragment.mHidden; } |