From f85b3d48d692e60af0b01ce75424ccb68e11b2bb Mon Sep 17 00:00:00 2001 From: George Mount Date: Mon, 6 Mar 2017 14:08:51 -0800 Subject: [PATCH] Excluded Views don't go through Transition. Bug 35832096 When entering or exiting Views were excluded, they were still being set to INVISIBLE during the exit transition. This made them disappear instantly. Instead, I've reverted back to the original implementation by not affecting excluded Views during the transition. This CL walks the transition and removes excluded Views from the enter/exit from being affected. Test: I5b1b75dd12a3914e35c1d0fb641850981a19f9c3 Change-Id: I2b00ba95575420bae690b1cd8d4894c98401da79 --- .../app/ActivityTransitionCoordinator.java | 55 +++++++++++++++++++ .../app/EnterTransitionCoordinator.java | 4 +- .../app/ExitTransitionCoordinator.java | 4 ++ core/java/android/transition/Transition.java | 4 +- 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index a5123504a4a1d..21a7ca733eb9b 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -28,6 +28,7 @@ import android.transition.TransitionListenerAdapter; import android.transition.TransitionSet; import android.transition.Visibility; import android.util.ArrayMap; +import android.util.ArraySet; import android.view.GhostView; import android.view.View; import android.view.ViewGroup; @@ -394,6 +395,60 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { return transition; } + /** + * Looks through the transition to see which Views have been included and which have been + * excluded. {@code views} will be modified to contain only those Views that are included + * in the transition. If {@code transition} is a TransitionSet, it will search through all + * contained Transitions to find targeted Views. + * + * @param transition The transition to look through for inclusion of Views + * @param views The list of Views that are to be checked for inclusion. Will be modified + * to remove all excluded Views, possibly leaving an empty list. + */ + protected static void removeExcludedViews(Transition transition, ArrayList views) { + ArraySet included = new ArraySet<>(); + findIncludedViews(transition, views, included); + views.clear(); + views.addAll(included); + } + + /** + * Looks through the transition to see which Views have been included. Only {@code views} + * will be examined for inclusion. If {@code transition} is a TransitionSet, it will search + * through all contained Transitions to find targeted Views. + * + * @param transition The transition to look through for inclusion of Views + * @param views The list of Views that are to be checked for inclusion. + * @param included Modified to contain all Views in views that have at least one Transition + * that affects it. + */ + private static void findIncludedViews(Transition transition, ArrayList views, + ArraySet included) { + if (transition instanceof TransitionSet) { + TransitionSet set = (TransitionSet) transition; + ArrayList includedViews = new ArrayList<>(); + final int numViews = views.size(); + for (int i = 0; i < numViews; i++) { + final View view = views.get(i); + if (transition.isValidTarget(view)) { + includedViews.add(view); + } + } + final int count = set.getTransitionCount(); + for (int i = 0; i < count; i++) { + findIncludedViews(set.getTransitionAt(i), includedViews, included); + } + } else { + final int numViews = views.size(); + for (int i = 0; i < numViews; i++) { + final View view = views.get(i); + if (transition.isValidTarget(view)) { + included.add(view); + } + } + } + } + protected static Transition mergeTransitions(Transition transition1, Transition transition2) { if (transition1 == null) { return transition2; diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 445b6871ddacc..ab847fd562a4a 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -132,7 +132,9 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { super.viewsReady(sharedElements); mIsReadyForTransition = true; hideViews(mSharedElements); - if (getViewsTransition() != null && mTransitioningViews != null) { + Transition viewsTransition = getViewsTransition(); + if (viewsTransition != null && mTransitioningViews != null) { + removeExcludedViews(viewsTransition, mTransitioningViews); stripOffscreenViews(); hideViews(mTransitioningViews); } diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 29e10d81c95d5..df31da9183f16 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -321,6 +321,10 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { Transition viewsTransition = null; if (mTransitioningViews != null && !mTransitioningViews.isEmpty()) { viewsTransition = configureTransition(getViewsTransition(), true); + removeExcludedViews(viewsTransition, mTransitioningViews); + if (mTransitioningViews.isEmpty()) { + viewsTransition = null; + } } if (viewsTransition == null) { viewsTransitionComplete(); diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index af2547e44b9fe..255a02938c32f 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -799,8 +799,10 @@ public abstract class Transition implements Cloneable { * targetId list. If the target parameter is null, then the target list * is not checked (this is in the case of ListView items, where the * views are ignored and only the ids are used). + * + * @hide */ - boolean isValidTarget(View target) { + public boolean isValidTarget(View target) { if (target == null) { return false; }