Skip to content

Commit 9985aaf

Browse files
George MountAndroid (Google) Code Review
authored andcommitted
Merge "Move shared elements to overlay when in a transition group." into lmp-dev
2 parents 669f8e7 + fe361d2 commit 9985aaf

7 files changed

Lines changed: 325 additions & 89 deletions

File tree

core/java/android/app/ActivityTransitionCoordinator.java

Lines changed: 135 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@
2929
import android.transition.Transition;
3030
import android.transition.TransitionSet;
3131
import android.util.ArrayMap;
32+
import android.view.GhostView;
3233
import android.view.View;
3334
import android.view.ViewGroup;
35+
import android.view.ViewGroupOverlay;
36+
import android.view.ViewParent;
3437
import android.view.ViewTreeObserver;
3538
import android.view.Window;
3639
import android.widget.ImageView;
@@ -202,6 +205,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
202205
final protected boolean mIsReturning;
203206
private Runnable mPendingTransition;
204207
private boolean mIsStartingTransition;
208+
private ArrayList<GhostViewListeners> mGhostViewListeners =
209+
new ArrayList<GhostViewListeners>();
205210

206211
public ActivityTransitionCoordinator(Window window,
207212
ArrayList<String> allSharedElementNames,
@@ -301,6 +306,12 @@ protected Transition setTargets(Transition transition, boolean add) {
301306
// By adding the transition after addTarget, we prevent addTarget from
302307
// affecting transition.
303308
set.addTransition(transition);
309+
310+
if (!add && mTransitioningViews != null && !mTransitioningViews.isEmpty()) {
311+
// Allow children of excluded transitioning views, but not the views themselves
312+
set = new TransitionSet().addTransition(set);
313+
}
314+
304315
return set;
305316
}
306317

@@ -362,7 +373,7 @@ protected void setResultReceiver(ResultReceiver resultReceiver) {
362373

363374
protected abstract Transition getViewsTransition();
364375

365-
private static void setSharedElementState(View view, String name, Bundle transitionArgs,
376+
private void setSharedElementState(View view, String name, Bundle transitionArgs,
366377
Matrix tempMatrix, RectF tempRect, int[] decorLoc) {
367378
Bundle sharedElementBundle = transitionArgs.getBundle(name);
368379
if (sharedElementBundle == null) {
@@ -396,9 +407,7 @@ private static void setSharedElementState(View view, String name, Bundle transit
396407
top -= decorLoc[1];
397408
} else {
398409
// Find the location in the view's parent
399-
ViewGroup parent = (ViewGroup) view.getParent();
400-
tempMatrix.reset();
401-
parent.transformMatrixToLocal(tempMatrix);
410+
getSharedElementParentMatrix(view, tempMatrix);
402411
tempRect.set(left, top, right, bottom);
403412
tempMatrix.mapRect(tempRect);
404413

@@ -418,6 +427,7 @@ private static void setSharedElementState(View view, String name, Bundle transit
418427
tempRect.set(0, 0, width, height);
419428
view.getMatrix().mapRect(tempRect);
420429

430+
ViewGroup parent = (ViewGroup) view.getParent();
421431
left = leftInParent - tempRect.left + parent.getScrollX();
422432
top = topInParent - tempRect.top + parent.getScrollY();
423433
right = left + width;
@@ -435,6 +445,13 @@ private static void setSharedElementState(View view, String name, Bundle transit
435445
view.layout(x, y, x + width, y + height);
436446
}
437447

448+
protected void getSharedElementParentMatrix(View view, Matrix matrix) {
449+
// Find the location in the view's parent
450+
ViewGroup parent = (ViewGroup) view.getParent();
451+
matrix.reset();
452+
parent.transformMatrixToLocal(matrix);
453+
}
454+
438455
protected ArrayList<SharedElementOriginalState> setSharedElementState(
439456
Bundle sharedElementState, final ArrayList<View> snapshots) {
440457
ArrayList<SharedElementOriginalState> originalImageState =
@@ -453,19 +470,24 @@ protected ArrayList<SharedElementOriginalState> setSharedElementState(
453470
}
454471
}
455472
mListener.setSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
473+
return originalImageState;
474+
}
475+
476+
protected void notifySharedElementEnd(ArrayList<View> snapshots) {
477+
mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
478+
}
456479

480+
protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
457481
getDecor().getViewTreeObserver().addOnPreDrawListener(
458482
new ViewTreeObserver.OnPreDrawListener() {
459483
@Override
460484
public boolean onPreDraw() {
461485
getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
462-
mListener.setSharedElementEnd(mSharedElementNames, mSharedElements,
463-
snapshots);
486+
notifySharedElementEnd(snapshots);
464487
return true;
465488
}
466489
}
467490
);
468-
return originalImageState;
469491
}
470492

471493
private static SharedElementOriginalState getOldSharedElementState(View view, String name,
@@ -572,8 +594,8 @@ protected long getFadeDuration() {
572594
}
573595

574596
protected static void setTransitionAlpha(ArrayList<View> views, float alpha) {
575-
int numSharedElements = views.size();
576-
for (int i = 0; i < numSharedElements; i++) {
597+
int count = views.size();
598+
for (int i = 0; i < count; i++) {
577599
views.get(i).setTransitionAlpha(alpha);
578600
}
579601
}
@@ -639,6 +661,82 @@ protected void transitionStarted() {
639661
mIsStartingTransition = false;
640662
}
641663

664+
protected void moveSharedElementsToOverlay() {
665+
int numSharedElements = mSharedElements.size();
666+
ViewGroup decor = getDecor();
667+
if (decor != null) {
668+
boolean moveWithParent = moveSharedElementWithParent();
669+
for (int i = 0; i < numSharedElements; i++) {
670+
View view = mSharedElements.get(i);
671+
GhostView.addGhost(view, decor);
672+
ViewGroup parent = (ViewGroup) view.getParent();
673+
if (moveWithParent && !isInTransitionGroup(parent, decor)) {
674+
GhostViewListeners listener =
675+
new GhostViewListeners(view, decor);
676+
parent.getViewTreeObserver().addOnPreDrawListener(listener);
677+
mGhostViewListeners.add(listener);
678+
}
679+
}
680+
}
681+
}
682+
683+
protected boolean moveSharedElementWithParent() {
684+
return true;
685+
}
686+
687+
public static boolean isInTransitionGroup(ViewParent viewParent, ViewGroup decor) {
688+
if (viewParent == decor || !(viewParent instanceof ViewGroup)) {
689+
return false;
690+
}
691+
ViewGroup parent = (ViewGroup) viewParent;
692+
if (parent.isTransitionGroup()) {
693+
return true;
694+
} else {
695+
return isInTransitionGroup(parent.getParent(), decor);
696+
}
697+
}
698+
699+
protected void moveSharedElementsFromOverlay() {
700+
ViewGroup decor = getDecor();
701+
if (decor != null) {
702+
ViewGroupOverlay overlay = decor.getOverlay();
703+
int count = mSharedElements.size();
704+
for (int i = 0; i < count; i++) {
705+
View sharedElement = mSharedElements.get(i);
706+
GhostView.removeGhost(sharedElement);
707+
}
708+
}
709+
int numListeners = mGhostViewListeners.size();
710+
for (int i = 0; i < numListeners; i++) {
711+
GhostViewListeners listener = mGhostViewListeners.get(i);
712+
ViewGroup parent = (ViewGroup) listener.getView().getParent();
713+
parent.getViewTreeObserver().removeOnPreDrawListener(listener);
714+
}
715+
mGhostViewListeners.clear();
716+
}
717+
718+
protected void setGhostVisibility(int visibility) {
719+
int numSharedElements = mSharedElements.size();
720+
for (int i = 0; i < numSharedElements; i++) {
721+
GhostView ghostView = GhostView.getGhost(mSharedElements.get(i));
722+
if (ghostView != null) {
723+
ghostView.setVisibility(visibility);
724+
}
725+
}
726+
}
727+
728+
protected void scheduleGhostVisibilityChange(final int visibility) {
729+
getDecor().getViewTreeObserver()
730+
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
731+
@Override
732+
public boolean onPreDraw() {
733+
getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
734+
setGhostVisibility(visibility);
735+
return true;
736+
}
737+
});
738+
}
739+
642740
protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter {
643741
@Override
644742
public void onTransitionStart(Transition transition) {
@@ -671,6 +769,34 @@ public Rect onGetEpicenter(Transition transition) {
671769
}
672770
}
673771

772+
private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
773+
private View mView;
774+
private ViewGroup mDecor;
775+
private Matrix mMatrix = new Matrix();
776+
777+
public GhostViewListeners(View view, ViewGroup decor) {
778+
mView = view;
779+
mDecor = decor;
780+
}
781+
782+
public View getView() {
783+
return mView;
784+
}
785+
786+
@Override
787+
public boolean onPreDraw() {
788+
ViewGroup parent = ((ViewGroup) mView.getParent());
789+
GhostView ghostView = GhostView.getGhost(mView);
790+
if (ghostView == null) {
791+
parent.getViewTreeObserver().removeOnPreDrawListener(this);
792+
} else {
793+
GhostView.calculateMatrix(mView, mDecor, mMatrix);
794+
ghostView.setMatrix(mMatrix);
795+
}
796+
return true;
797+
}
798+
}
799+
674800
static class SharedElementOriginalState {
675801
int mLeft;
676802
int mTop;
@@ -681,5 +807,4 @@ static class SharedElementOriginalState {
681807
ImageView.ScaleType mScaleType;
682808
Matrix mMatrix;
683809
}
684-
685810
}

0 commit comments

Comments
 (0)