From c18f4cc0f2dfb05b22c6187c5c2c2dead4f504a5 Mon Sep 17 00:00:00 2001 From: Dake Gu Date: Fri, 11 Jul 2014 17:48:37 -0700 Subject: [PATCH] ActivityTransition: restore callee activity shared element position Move the shared element of callee activity to animation start position, then restore the measured size and locations to original values before call requestLayout(), this fixes cases for RecyclerView optimized layout which offsets siblings by delta of measure size. Change-Id: I6e43c036e26986605ff008aba476e30ebd270fd1 --- .../app/ActivityTransitionCoordinator.java | 75 +++++++++++++------ .../app/EnterTransitionCoordinator.java | 4 +- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index 15be9b18289bf..e07421983f1b6 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -403,20 +403,18 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { view.layout(left, top, right, bottom); } - protected ArrayMap> setSharedElementState( + protected ArrayList setSharedElementState( Bundle sharedElementState, final ArrayList snapshots) { - ArrayMap> originalImageState = - new ArrayMap>(); + ArrayList originalImageState = + new ArrayList(); if (sharedElementState != null) { int[] tempLoc = new int[2]; for (int i = 0; i < mSharedElementNames.size(); i++) { View sharedElement = mSharedElements.get(i); String name = mSharedElementNames.get(i); - Pair originalState = getOldImageState(sharedElement, + SharedElementOriginalState originalState = getOldSharedElementState(sharedElement, name, sharedElementState); - if (originalState != null) { - originalImageState.put((ImageView) sharedElement, originalState); - } + originalImageState.add(originalState); View parent = (View) sharedElement.getParent(); parent.getLocationOnScreen(tempLoc); setSharedElementState(sharedElement, name, sharedElementState, tempLoc); @@ -438,29 +436,34 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { return originalImageState; } - private static Pair getOldImageState(View view, String name, + private static SharedElementOriginalState getOldSharedElementState(View view, String name, Bundle transitionArgs) { + + SharedElementOriginalState state = new SharedElementOriginalState(); + state.mLeft = view.getLeft(); + state.mTop = view.getTop(); + state.mRight = view.getRight(); + state.mBottom = view.getBottom(); + state.mMeasuredWidth = view.getMeasuredWidth(); + state.mMeasuredHeight = view.getMeasuredHeight(); if (!(view instanceof ImageView)) { - return null; + return state; } Bundle bundle = transitionArgs.getBundle(name); if (bundle == null) { - return null; + return state; } int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1); if (scaleTypeInt < 0) { - return null; + return state; } ImageView imageView = (ImageView) view; - ImageView.ScaleType originalScaleType = imageView.getScaleType(); - - Matrix originalMatrix = null; - if (originalScaleType == ImageView.ScaleType.MATRIX) { - originalMatrix = new Matrix(imageView.getImageMatrix()); + state.mScaleType = imageView.getScaleType(); + if (state.mScaleType == ImageView.ScaleType.MATRIX) { + state.mMatrix = new Matrix(imageView.getImageMatrix()); } - - return Pair.create(originalScaleType, originalMatrix); + return state; } protected ArrayList createSnapshots(Bundle state, Collection names) { @@ -489,13 +492,26 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { return snapshots; } - protected static void setOriginalImageViewState( - ArrayMap> originalState) { + protected static void setOriginalSharedElementState(ArrayList sharedElements, + ArrayList originalState) { for (int i = 0; i < originalState.size(); i++) { - ImageView imageView = originalState.keyAt(i); - Pair state = originalState.valueAt(i); - imageView.setScaleType(state.first); - imageView.setImageMatrix(state.second); + View view = sharedElements.get(i); + SharedElementOriginalState state = originalState.get(i); + if (view instanceof ImageView && state.mScaleType != null) { + ImageView imageView = (ImageView) view; + imageView.setScaleType(state.mScaleType); + if (state.mScaleType == ImageView.ScaleType.MATRIX) { + imageView.setImageMatrix(state.mMatrix); + } + } + // origignal widthspec might be AT_MOST, but it should work for most + // cases. + int widthSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredWidth, + View.MeasureSpec.EXACTLY); + int heightSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredHeight, + View.MeasureSpec.EXACTLY); + view.measure(widthSpec, heightSpec); + view.layout(state.mLeft, state.mTop, state.mRight, state.mBottom); } } @@ -622,4 +638,15 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } } + static class SharedElementOriginalState { + int mLeft; + int mTop; + int mRight; + int mBottom; + int mMeasuredWidth; + int mMeasuredHeight; + ImageView.ScaleType mScaleType; + Matrix mMatrix; + } + } diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index f50c93b3cc0e4..1326064341002 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -282,7 +282,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { ArrayList sharedElementSnapshots = createSnapshots(sharedElementState, mSharedElementNames); setTransitionAlpha(mSharedElements, 1); - ArrayMap> originalImageViewState = + ArrayList originalImageViewState = setSharedElementState(sharedElementState, sharedElementSnapshots); requestLayoutForSharedElements(); @@ -294,7 +294,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { startEnterTransition(transition); } - setOriginalImageViewState(originalImageViewState); + setOriginalSharedElementState(mSharedElements, originalImageViewState); if (mResultReceiver != null) { // We can't trust that the view will disappear on the same frame that the shared