diff options
author | Chet Haase <chet@google.com> | 2013-08-26 23:29:34 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-26 23:29:35 +0000 |
commit | be6cf71dc52ce2fdecc5d432abf1b30a1c62e376 (patch) | |
tree | 9641a4e45b1099fa322757c7844911dffeab6de7 | |
parent | 04e3a14c2d51c2515dcae9278550d35269a9797a (diff) | |
parent | 35a457a3bac0851a1fabd6cda58d1ea67f997b33 (diff) | |
download | frameworks_base-be6cf71dc52ce2fdecc5d432abf1b30a1c62e376.zip frameworks_base-be6cf71dc52ce2fdecc5d432abf1b30a1c62e376.tar.gz frameworks_base-be6cf71dc52ce2fdecc5d432abf1b30a1c62e376.tar.bz2 |
Merge "Tweak visibility logic for inflated view scenarios" into klp-dev
-rw-r--r-- | core/java/android/view/transition/Visibility.java | 104 |
1 files changed, 72 insertions, 32 deletions
diff --git a/core/java/android/view/transition/Visibility.java b/core/java/android/view/transition/Visibility.java index 96ea044..4df53da 100644 --- a/core/java/android/view/transition/Visibility.java +++ b/core/java/android/view/transition/Visibility.java @@ -29,11 +29,25 @@ import android.view.ViewParent; * views exist in the current view hierarchy. The class is intended to be a * utility for subclasses such as {@link Fade}, which use this visibility * information to determine the specific animations to run when visibility - * changes occur. Subclasses should implement one or more of the methods - * {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int)}, - * {@link #disappear(ViewGroup, TransitionValues, int, TransitionValues, int)}, - * {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int)}, and + * changes occur. Subclasses should implement one or both of the methods + * {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int), and * {@link #disappear(ViewGroup, TransitionValues, int, TransitionValues, int)}. + * + * <p>Note that a view's visibility change is determined by both whether the view + * itself is changing and whether its parent hierarchy's visibility is changing. + * That is, a view that appears in the end scene will only trigger a call to + * {@link #appear(android.view.ViewGroup, TransitionValues, int, TransitionValues, int) + * appear()} if its parent hierarchy was stable between the start and end scenes. + * This is done to avoid causing a visibility transition on every node in a hierarchy + * when only the top-most node is the one that should be transitioned in/out. + * Stability is determined by either the parent hierarchy views being the same + * between scenes or, if scenes are inflated from layout resource files and thus + * have result in different view instances, if the views represented by + * the ids of those parents are stable. This means that visibility determination + * is more effective with inflated view hierarchies if ids are used. + * The exception to this is when the visibility subclass transition is + * targeted at specific views, in which case the visibility of parent views + * is ignored.</p> */ public abstract class Visibility extends Transition { @@ -49,8 +63,8 @@ public abstract class Visibility extends Transition { boolean fadeIn; int startVisibility; int endVisibility; - View startParent; - View endParent; + ViewGroup startParent; + ViewGroup endParent; } // Temporary structure, used in calculating state in setup() and play() @@ -93,28 +107,47 @@ public abstract class Visibility extends Transition { return visibility == View.VISIBLE && parent != null; } - private boolean isHierarchyVisibilityChanging(ViewGroup sceneRoot, ViewGroup view) { + /** + * Tests whether the hierarchy, up to the scene root, changes visibility between + * start and end scenes. This is done to ensure that a view that changes visibility + * is only animated if that view's parent was stable between scenes; we should not + * fade an entire hierarchy, but rather just the top-most node in the hierarchy that + * changed visibility. Note that both the start and end parents are passed in + * because the instances may differ for the same view due to layout inflation + * between scenes. + * + * @param sceneRoot The root of the scene hierarchy + * @param startView The container view in the start scene + * @param endView The container view in the end scene + * @return true if the parent hierarchy experienced a visibility change, false + * otherwise + */ + private boolean isHierarchyVisibilityChanging(ViewGroup sceneRoot, ViewGroup startView, + ViewGroup endView) { - if (view == sceneRoot) { + if (startView == sceneRoot || endView == sceneRoot) { return false; } - TransitionValues startValues = getTransitionValues(view, true); - TransitionValues endValues = getTransitionValues(view, false); + TransitionValues startValues = startView != null ? + getTransitionValues(startView, true) : getTransitionValues(endView, true); + TransitionValues endValues = endView != null ? + getTransitionValues(endView, false) : getTransitionValues(startView, false); if (startValues == null || endValues == null) { return true; } - int startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY); - View startParent = (View) startValues.values.get(PROPNAME_PARENT); - int endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY); - View endParent = (View) endValues.values.get(PROPNAME_PARENT); + Integer visibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY); + int startVisibility = (visibility != null) ? visibility : -1; + ViewGroup startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT); + visibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY); + int endVisibility = (visibility != null) ? visibility : -1; + ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT); if (startVisibility != endVisibility || startParent != endParent) { return true; } - ViewParent parent = view.getParent(); - if (parent instanceof ViewGroup && parent != sceneRoot) { - return isHierarchyVisibilityChanging(sceneRoot, (ViewGroup) parent); + if (startParent != null || endParent != null) { + return isHierarchyVisibilityChanging(sceneRoot, startParent, endParent); } return false; } @@ -126,14 +159,14 @@ public abstract class Visibility extends Transition { visInfo.fadeIn = false; if (startValues != null) { visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY); - visInfo.startParent = (View) startValues.values.get(PROPNAME_PARENT); + visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT); } else { visInfo.startVisibility = -1; visInfo.startParent = null; } if (endValues != null) { visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY); - visInfo.endParent = (View) endValues.values.get(PROPNAME_PARENT); + visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT); } else { visInfo.endVisibility = -1; visInfo.endParent = null; @@ -177,20 +210,27 @@ public abstract class Visibility extends Transition { protected Animator play(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) { VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues); - // Ensure not in parent hierarchy that's also becoming visible/invisible if (visInfo.visibilityChange) { - ViewGroup parent = (ViewGroup) ((visInfo.endParent != null) ? - visInfo.endParent : visInfo.startParent); - if (parent != null) { - if (!isHierarchyVisibilityChanging(sceneRoot, parent)) { - if (visInfo.fadeIn) { - return appear(sceneRoot, startValues, visInfo.startVisibility, - endValues, visInfo.endVisibility); - } else { - return disappear(sceneRoot, startValues, visInfo.startVisibility, - endValues, visInfo.endVisibility - ); - } + // Only transition views that are either targets of this transition + // or whose parent hierarchies remain stable between scenes + boolean isTarget = false; + if (mTargets != null || mTargetIds != null) { + View startView = startValues != null ? startValues.view : null; + View endView = endValues != null ? endValues.view : null; + int startId = startView != null ? startView.getId() : -1; + int endId = endView != null ? endView.getId() : -1; + isTarget = isValidTarget(startView, startId) || isValidTarget(endView, endId); + } + if (isTarget || ((visInfo.startParent != null || visInfo.endParent != null) && + !isHierarchyVisibilityChanging(sceneRoot, + visInfo.startParent, visInfo.endParent))) { + if (visInfo.fadeIn) { + return appear(sceneRoot, startValues, visInfo.startVisibility, + endValues, visInfo.endVisibility); + } else { + return disappear(sceneRoot, startValues, visInfo.startVisibility, + endValues, visInfo.endVisibility + ); } } } |