2929import android .transition .Transition ;
3030import android .transition .TransitionSet ;
3131import android .util .ArrayMap ;
32+ import android .view .GhostView ;
3233import android .view .View ;
3334import android .view .ViewGroup ;
35+ import android .view .ViewGroupOverlay ;
36+ import android .view .ViewParent ;
3437import android .view .ViewTreeObserver ;
3538import android .view .Window ;
3639import 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