FileDocCategorySizeDatePackage
Visibility.javaAPI DocAndroid 5.1 API23628Thu Mar 12 22:22:10 GMT 2015android.transition

Visibility

public 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_IN
Mode 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_OUT
Mode 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
booleanareValuesChanged(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 voidcaptureEndValues(TransitionValues transitionValues)

        captureValues(transitionValues, mForcedEndVisibility);
    
public voidcaptureStartValues(TransitionValues transitionValues)

        captureValues(transitionValues, mForcedStartVisibility);
    
private voidcaptureValues(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.AnimatorcreateAnimator(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 voidforceVisibility(int visibility, boolean isStartValue)

hide

        if (isStartValue) {
            mForcedStartVisibility = visibility;
        } else {
            mForcedEndVisibility = visibility;
        }
    
public intgetMode()
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}.

attr
ref android.R.styleable#VisibilityTransition_transitionVisibilityMode

        return mMode;
    
public java.lang.String[]getTransitionProperties()

        return sTransitionProperties;
    
private android.transition.Visibility$VisibilityInfogetVisibilityChangeInfo(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 booleanisVisible(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.

param
values The TransitionValues object that holds the information by which visibility is determined.
return
True if the view reference by values is visible, false otherwise.

        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.AnimatoronAppear(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.

param
sceneRoot The root of the transition hierarchy
param
startValues The target values in the start scene
param
startVisibility The target visibility in the start scene
param
endValues The target values in the end scene
param
endVisibility The target visibility in the end scene
return
An Animator to be started at the appropriate time in the overall transition for this scene change. A null value means no animation should be run.

        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.AnimatoronAppear(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)}.

param
sceneRoot The root of the transition hierarchy
param
view The View to make appear. This will be in the target scene's View hierarchy and will be VISIBLE.
param
startValues The target values in the start scene
param
endValues The target values in the end scene
return
An Animator to be started at the appropriate time in the overall transition for this scene change. A null value means no animation should be run.

        return null;
    
public android.animation.AnimatoronDisappear(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.

param
sceneRoot The root of the transition hierarchy
param
startValues The target values in the start scene
param
startVisibility The target visibility in the start scene
param
endValues The target values in the end scene
param
endVisibility The target visibility in the end scene
return
An Animator to be started at the appropriate time in the overall transition for this scene change. A null value means no animation should be run.

        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.AnimatoronDisappear(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)}.

param
sceneRoot The root of the transition hierarchy
param
view The View to make disappear. This will be in the target scene's View hierarchy or in an {@link android.view.ViewGroupOverlay} and will be VISIBLE.
param
startValues The target values in the start scene
param
endValues The target values in the end scene
return
An Animator to be started at the appropriate time in the overall transition for this scene change. A null value means no animation should be run.

        return null;
    
public voidsetMode(int mode)
Changes the transition to support appearing and/or disappearing Views, depending on mode.

param
mode The behavior supported by this transition, a combination of {@link #MODE_IN} and {@link #MODE_OUT}.
attr
ref android.R.styleable#VisibilityTransition_transitionVisibilityMode

        if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
            throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
        }
        mMode = mode;