Merge "Tweak visibility logic for inflated view scenarios" into klp-dev
This commit is contained in:
@@ -29,11 +29,25 @@ import android.view.ViewParent;
|
|||||||
* views exist in the current view hierarchy. The class is intended to be a
|
* 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
|
* utility for subclasses such as {@link Fade}, which use this visibility
|
||||||
* information to determine the specific animations to run when visibility
|
* information to determine the specific animations to run when visibility
|
||||||
* changes occur. Subclasses should implement one or more of the methods
|
* changes occur. Subclasses should implement one or both of the methods
|
||||||
* {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int)},
|
* {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int), and
|
||||||
* {@link #disappear(ViewGroup, TransitionValues, int, TransitionValues, int)},
|
|
||||||
* {@link #appear(ViewGroup, TransitionValues, int, TransitionValues, int)}, and
|
|
||||||
* {@link #disappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
|
* {@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 {
|
public abstract class Visibility extends Transition {
|
||||||
|
|
||||||
@@ -49,8 +63,8 @@ public abstract class Visibility extends Transition {
|
|||||||
boolean fadeIn;
|
boolean fadeIn;
|
||||||
int startVisibility;
|
int startVisibility;
|
||||||
int endVisibility;
|
int endVisibility;
|
||||||
View startParent;
|
ViewGroup startParent;
|
||||||
View endParent;
|
ViewGroup endParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary structure, used in calculating state in setup() and play()
|
// 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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
TransitionValues startValues = getTransitionValues(view, true);
|
TransitionValues startValues = startView != null ?
|
||||||
TransitionValues endValues = getTransitionValues(view, false);
|
getTransitionValues(startView, true) : getTransitionValues(endView, true);
|
||||||
|
TransitionValues endValues = endView != null ?
|
||||||
|
getTransitionValues(endView, false) : getTransitionValues(startView, false);
|
||||||
|
|
||||||
if (startValues == null || endValues == null) {
|
if (startValues == null || endValues == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
|
Integer visibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
|
||||||
View startParent = (View) startValues.values.get(PROPNAME_PARENT);
|
int startVisibility = (visibility != null) ? visibility : -1;
|
||||||
int endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
|
ViewGroup startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
|
||||||
View endParent = (View) endValues.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) {
|
if (startVisibility != endVisibility || startParent != endParent) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewParent parent = view.getParent();
|
if (startParent != null || endParent != null) {
|
||||||
if (parent instanceof ViewGroup && parent != sceneRoot) {
|
return isHierarchyVisibilityChanging(sceneRoot, startParent, endParent);
|
||||||
return isHierarchyVisibilityChanging(sceneRoot, (ViewGroup) parent);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -126,14 +159,14 @@ public abstract class Visibility extends Transition {
|
|||||||
visInfo.fadeIn = false;
|
visInfo.fadeIn = false;
|
||||||
if (startValues != null) {
|
if (startValues != null) {
|
||||||
visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
|
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 {
|
} else {
|
||||||
visInfo.startVisibility = -1;
|
visInfo.startVisibility = -1;
|
||||||
visInfo.startParent = null;
|
visInfo.startParent = null;
|
||||||
}
|
}
|
||||||
if (endValues != null) {
|
if (endValues != null) {
|
||||||
visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
|
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 {
|
} else {
|
||||||
visInfo.endVisibility = -1;
|
visInfo.endVisibility = -1;
|
||||||
visInfo.endParent = null;
|
visInfo.endParent = null;
|
||||||
@@ -177,20 +210,27 @@ public abstract class Visibility extends Transition {
|
|||||||
protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
|
protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
|
||||||
TransitionValues endValues) {
|
TransitionValues endValues) {
|
||||||
VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
|
VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
|
||||||
// Ensure not in parent hierarchy that's also becoming visible/invisible
|
|
||||||
if (visInfo.visibilityChange) {
|
if (visInfo.visibilityChange) {
|
||||||
ViewGroup parent = (ViewGroup) ((visInfo.endParent != null) ?
|
// Only transition views that are either targets of this transition
|
||||||
visInfo.endParent : visInfo.startParent);
|
// or whose parent hierarchies remain stable between scenes
|
||||||
if (parent != null) {
|
boolean isTarget = false;
|
||||||
if (!isHierarchyVisibilityChanging(sceneRoot, parent)) {
|
if (mTargets != null || mTargetIds != null) {
|
||||||
if (visInfo.fadeIn) {
|
View startView = startValues != null ? startValues.view : null;
|
||||||
return appear(sceneRoot, startValues, visInfo.startVisibility,
|
View endView = endValues != null ? endValues.view : null;
|
||||||
endValues, visInfo.endVisibility);
|
int startId = startView != null ? startView.getId() : -1;
|
||||||
} else {
|
int endId = endView != null ? endView.getId() : -1;
|
||||||
return disappear(sceneRoot, startValues, visInfo.startVisibility,
|
isTarget = isValidTarget(startView, startId) || isValidTarget(endView, endId);
|
||||||
endValues, visInfo.endVisibility
|
}
|
||||||
);
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user