Visibilitypublic abstract class Visibility extends Transition This transition tracks changes to the visibility of target views in the
start and end scenes. Visibility is determined not just by the
{@link View#setVisibility(int)} state of views, but also whether
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 both of the methods
{@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
{@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
{@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
{@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}. |
Fields Summary |
---|
static final String | PROPNAME_VISIBILITY | private static final String | PROPNAME_PARENT | private static final String | PROPNAME_SCREEN_LOCATION | public static final int | MODE_INMode used in {@link #setMode(int)} to make the transition
operate on targets that are appearing. Maybe be combined with
{@link #MODE_OUT} to target Visibility changes both in and out. | public static final int | MODE_OUTMode used in {@link #setMode(int)} to make the transition
operate on targets that are disappearing. Maybe be combined with
{@link #MODE_IN} to target Visibility changes both in and out. | private static final String[] | sTransitionProperties | private int | mMode | private int | mForcedStartVisibility | private int | mForcedEndVisibility |
Constructors Summary |
---|
public Visibility()
| public Visibility(android.content.Context context, android.util.AttributeSet attrs)
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition);
int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0);
a.recycle();
if (mode != 0) {
setMode(mode);
}
|
Methods Summary |
---|
boolean | areValuesChanged(TransitionValues oldValues, TransitionValues newValues)
if (oldValues == null && newValues == null) {
return false;
}
if (oldValues != null && newValues != null &&
newValues.values.containsKey(PROPNAME_VISIBILITY) !=
oldValues.values.containsKey(PROPNAME_VISIBILITY)) {
// The transition wasn't targeted in either the start or end, so it couldn't
// have changed.
return false;
}
VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE ||
changeInfo.endVisibility == View.VISIBLE);
| public void | captureEndValues(TransitionValues transitionValues)
captureValues(transitionValues, mForcedEndVisibility);
| public void | captureStartValues(TransitionValues transitionValues)
captureValues(transitionValues, mForcedStartVisibility);
| private void | captureValues(TransitionValues transitionValues, int forcedVisibility)
int visibility;
if (forcedVisibility != -1) {
visibility = forcedVisibility;
} else {
visibility = transitionValues.view.getVisibility();
}
transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
int[] loc = new int[2];
transitionValues.view.getLocationOnScreen(loc);
transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
| public android.animation.Animator | createAnimator(android.view.ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues)
VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
if (visInfo.visibilityChange
&& (visInfo.startParent != null || visInfo.endParent != null)) {
if (visInfo.fadeIn) {
return onAppear(sceneRoot, startValues, visInfo.startVisibility,
endValues, visInfo.endVisibility);
} else {
return onDisappear(sceneRoot, startValues, visInfo.startVisibility,
endValues, visInfo.endVisibility
);
}
}
return null;
| public void | forceVisibility(int visibility, boolean isStartValue)
if (isStartValue) {
mForcedStartVisibility = visibility;
} else {
mForcedEndVisibility = visibility;
}
| public int | getMode()Returns whether appearing and/or disappearing Views are supported.
Returns whether appearing and/or disappearing Views are supported. A combination of
{@link #MODE_IN} and {@link #MODE_OUT}.
return mMode;
| public java.lang.String[] | getTransitionProperties()
return sTransitionProperties;
| private android.transition.Visibility$VisibilityInfo | getVisibilityChangeInfo(TransitionValues startValues, TransitionValues endValues)
final VisibilityInfo visInfo = new VisibilityInfo();
visInfo.visibilityChange = false;
visInfo.fadeIn = false;
if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
} else {
visInfo.startVisibility = -1;
visInfo.startParent = null;
}
if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
} else {
visInfo.endVisibility = -1;
visInfo.endParent = null;
}
if (startValues != null && endValues != null) {
if (visInfo.startVisibility == visInfo.endVisibility &&
visInfo.startParent == visInfo.endParent) {
return visInfo;
} else {
if (visInfo.startVisibility != visInfo.endVisibility) {
if (visInfo.startVisibility == View.VISIBLE) {
visInfo.fadeIn = false;
visInfo.visibilityChange = true;
} else if (visInfo.endVisibility == View.VISIBLE) {
visInfo.fadeIn = true;
visInfo.visibilityChange = true;
}
// no visibilityChange if going between INVISIBLE and GONE
} else if (visInfo.startParent != visInfo.endParent) {
if (visInfo.endParent == null) {
visInfo.fadeIn = false;
visInfo.visibilityChange = true;
} else if (visInfo.startParent == null) {
visInfo.fadeIn = true;
visInfo.visibilityChange = true;
}
}
}
} else if (startValues == null && visInfo.endVisibility == View.VISIBLE) {
visInfo.fadeIn = true;
visInfo.visibilityChange = true;
} else if (endValues == null && visInfo.startVisibility == View.VISIBLE) {
visInfo.fadeIn = false;
visInfo.visibilityChange = true;
}
return visInfo;
| public boolean | isVisible(TransitionValues values)Returns whether the view is 'visible' according to the given values
object. This is determined by testing the same properties in the values
object that are used to determine whether the object is appearing or
disappearing in the {@link
Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)}
method. This method can be called by, for example, subclasses that want
to know whether the object is visible in the same way that Visibility
determines it for the actual animation.
if (values == null) {
return false;
}
int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
View parent = (View) values.values.get(PROPNAME_PARENT);
return visibility == View.VISIBLE && parent != null;
| public android.animation.Animator | onAppear(android.view.ViewGroup sceneRoot, TransitionValues startValues, int startVisibility, TransitionValues endValues, int endVisibility)The default implementation of this method calls
{@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
Subclasses should override this method or
{@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
if they need to create an Animator when targets appear.
The method should only be called by the Visibility class; it is
not intended to be called from external classes.
if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
return null;
}
if (startValues == null) {
VisibilityInfo parentVisibilityInfo = null;
View endParent = (View) endValues.view.getParent();
TransitionValues startParentValues = getMatchedTransitionValues(endParent,
false);
TransitionValues endParentValues = getTransitionValues(endParent, false);
parentVisibilityInfo =
getVisibilityChangeInfo(startParentValues, endParentValues);
if (parentVisibilityInfo.visibilityChange) {
return null;
}
}
return onAppear(sceneRoot, endValues.view, startValues, endValues);
| public android.animation.Animator | onAppear(android.view.ViewGroup sceneRoot, android.view.View view, TransitionValues startValues, TransitionValues endValues)The default implementation of this method returns a null Animator. Subclasses should
override this method to make targets appear with the desired transition. The
method should only be called from
{@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
return null;
| public android.animation.Animator | onDisappear(android.view.ViewGroup sceneRoot, TransitionValues startValues, int startVisibility, TransitionValues endValues, int endVisibility)Subclasses should override this method or
{@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}
if they need to create an Animator when targets disappear.
The method should only be called by the Visibility class; it is
not intended to be called from external classes.
The default implementation of this method attempts to find a View to use to call
{@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)},
based on the situation of the View in the View hierarchy. For example,
if a View was simply removed from its parent, then the View will be added
into a {@link android.view.ViewGroupOverlay} and passed as the view
parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE},
then it can be used as the view and the visibility will be changed
to {@link View#VISIBLE} for the duration of the animation. However, if a View
is in a hierarchy which is also altering its visibility, the situation can be
more complicated. In general, if a view that is no longer in the hierarchy in
the end scene still has a parent (so its parent hierarchy was removed, but it
was not removed from its parent), then it will be left alone to avoid side-effects from
improperly removing it from its parent. The only exception to this is if
the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int,
android.content.Context) created from a layout resource file}, then it is considered
safe to un-parent the starting scene view in order to make it disappear.
if ((mMode & MODE_OUT) != MODE_OUT) {
return null;
}
View startView = (startValues != null) ? startValues.view : null;
View endView = (endValues != null) ? endValues.view : null;
View overlayView = null;
View viewToKeep = null;
if (endView == null || endView.getParent() == null) {
if (endView != null) {
// endView was removed from its parent - add it to the overlay
overlayView = endView;
} else if (startView != null) {
// endView does not exist. Use startView only under certain
// conditions, because placing a view in an overlay necessitates
// it being removed from its current parent
if (startView.getParent() == null) {
// no parent - safe to use
overlayView = startView;
} else if (startView.getParent() instanceof View) {
View startParent = (View) startView.getParent();
TransitionValues startParentValues = getTransitionValues(startParent, true);
TransitionValues endParentValues = getMatchedTransitionValues(startParent,
true);
VisibilityInfo parentVisibilityInfo =
getVisibilityChangeInfo(startParentValues, endParentValues);
if (!parentVisibilityInfo.visibilityChange) {
overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
startParent);
} else if (startParent.getParent() == null) {
int id = startParent.getId();
if (id != View.NO_ID && sceneRoot.findViewById(id) != null
&& mCanRemoveViews) {
// no parent, but its parent is unparented but the parent
// hierarchy has been replaced by a new hierarchy with the same id
// and it is safe to un-parent startView
overlayView = startView;
}
}
}
}
} else {
// visibility change
if (endVisibility == View.INVISIBLE) {
viewToKeep = endView;
} else {
// Becoming GONE
if (startView == endView) {
viewToKeep = endView;
} else {
overlayView = startView;
}
}
}
final int finalVisibility = endVisibility;
final ViewGroup finalSceneRoot = sceneRoot;
if (overlayView != null) {
// TODO: Need to do this for general case of adding to overlay
int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
int screenX = screenLoc[0];
int screenY = screenLoc[1];
int[] loc = new int[2];
sceneRoot.getLocationOnScreen(loc);
overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
sceneRoot.getOverlay().add(overlayView);
Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
if (animator == null) {
sceneRoot.getOverlay().remove(overlayView);
} else {
final View finalOverlayView = overlayView;
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finalSceneRoot.getOverlay().remove(finalOverlayView);
}
});
}
return animator;
}
if (viewToKeep != null) {
int originalVisibility = -1;
final boolean isForcedVisibility = mForcedStartVisibility != -1 ||
mForcedEndVisibility != -1;
if (!isForcedVisibility) {
originalVisibility = viewToKeep.getVisibility();
viewToKeep.setVisibility(View.VISIBLE);
}
Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
if (animator != null) {
final View finalViewToKeep = viewToKeep;
animator.addListener(new AnimatorListenerAdapter() {
boolean mCanceled = false;
@Override
public void onAnimationPause(Animator animation) {
if (!mCanceled && !isForcedVisibility) {
finalViewToKeep.setVisibility(finalVisibility);
}
}
@Override
public void onAnimationResume(Animator animation) {
if (!mCanceled && !isForcedVisibility) {
finalViewToKeep.setVisibility(View.VISIBLE);
}
}
@Override
public void onAnimationCancel(Animator animation) {
mCanceled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mCanceled) {
if (isForcedVisibility) {
finalViewToKeep.setTransitionAlpha(0);
} else {
finalViewToKeep.setVisibility(finalVisibility);
}
}
}
});
} else if (!isForcedVisibility) {
viewToKeep.setVisibility(originalVisibility);
}
return animator;
}
return null;
| public android.animation.Animator | onDisappear(android.view.ViewGroup sceneRoot, android.view.View view, TransitionValues startValues, TransitionValues endValues)The default implementation of this method returns a null Animator. Subclasses should
override this method to make targets disappear with the desired transition. The
method should only be called from
{@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
return null;
| public void | setMode(int mode)Changes the transition to support appearing and/or disappearing Views, depending
on mode .
if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
}
mMode = mode;
|
|