Visibility.java revision cba01b2310e78fc2114ceed285f4e134469ae62b
1faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/*
2faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Copyright (C) 2013 The Android Open Source Project
3faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
4faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * you may not use this file except in compliance with the License.
6faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * You may obtain a copy of the License at
7faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
8faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase *
10faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Unless required by applicable law or agreed to in writing, software
11faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * See the License for the specific language governing permissions and
14faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * limitations under the License.
15faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */
166ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
17d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haasepackage android.transition;
18faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
19ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport com.android.internal.R;
20ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
21faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.Animator;
22d6107a3170df61d9e776fcd5666acfc9135c6f16George Mountimport android.animation.AnimatorListenerAdapter;
23ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.content.Context;
24ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.content.res.TypedArray;
25d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mountimport android.graphics.Bitmap;
26d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mountimport android.graphics.Canvas;
27d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mountimport android.graphics.drawable.BitmapDrawable;
28ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.util.AttributeSet;
29faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.View;
30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup;
31faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/**
32faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * This transition tracks changes to the visibility of target views in the
33faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * start and end scenes. Visibility is determined not just by the
34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * {@link View#setVisibility(int)} state of views, but also whether
35faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * views exist in the current view hierarchy. The class is intended to be a
36faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * utility for subclasses such as {@link Fade}, which use this visibility
37faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * information to determine the specific animations to run when visibility
3835a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase * changes occur. Subclasses should implement one or both of the methods
39d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
40d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
41d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
42d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
43faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */
44faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haasepublic abstract class Visibility extends Transition {
45faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
466ceac2eafbb43dafd18bf547fee6fe51aee6b59bGeorge Mount    static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    private static final String PROPNAME_PARENT = "android:visibility:parent";
48d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
49d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
5018ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    /**
5118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * Mode used in {@link #setMode(int)} to make the transition
5218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * operate on targets that are appearing. Maybe be combined with
53ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount     * {@link #MODE_OUT} to target Visibility changes both in and out.
5418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     */
55ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount    public static final int MODE_IN = 0x1;
5618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
5718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    /**
5818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * Mode used in {@link #setMode(int)} to make the transition
5918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * operate on targets that are disappearing. Maybe be combined with
60ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount     * {@link #MODE_IN} to target Visibility changes both in and out.
6118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     */
62ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount    public static final int MODE_OUT = 0x2;
6318ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
64af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase    private static final String[] sTransitionProperties = {
65199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            PROPNAME_VISIBILITY,
66199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    };
67faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
686ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private static class VisibilityInfo {
696ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        boolean visibilityChange;
706ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        boolean fadeIn;
716ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        int startVisibility;
726ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        int endVisibility;
7335a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase        ViewGroup startParent;
7435a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase        ViewGroup endParent;
756ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
77ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount    private int mMode = MODE_IN | MODE_OUT;
7818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
79b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    private int mForcedStartVisibility = -1;
80b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    private int mForcedEndVisibility = -1;
81b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
82ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public Visibility() {}
83ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
84ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public Visibility(Context context, AttributeSet attrs) {
85ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        super(context, attrs);
86ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition);
873b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner        int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0);
88ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        a.recycle();
89ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (mode != 0) {
90ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            setMode(mode);
91ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
92ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
93ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
9418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    /**
9518ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * Changes the transition to support appearing and/or disappearing Views, depending
9618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * on <code>mode</code>.
9718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     *
9818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * @param mode The behavior supported by this transition, a combination of
99ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount     *             {@link #MODE_IN} and {@link #MODE_OUT}.
1003b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner     * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
10118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     */
10218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    public void setMode(int mode) {
103ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount        if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
104ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount            throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
10518ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        }
10618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        mMode = mode;
10718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    }
10818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
109ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
110ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Returns whether appearing and/or disappearing Views are supported.
111ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *
112ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Returns whether appearing and/or disappearing Views are supported. A combination of
113ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount     *         {@link #MODE_IN} and {@link #MODE_OUT}.
1143b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner     * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
115ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
116ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public int getMode() {
117ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        return mMode;
118ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
119ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
120faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
121199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String[] getTransitionProperties() {
122199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return sTransitionProperties;
123199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
124199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
125b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    private void captureValues(TransitionValues transitionValues, int forcedVisibility) {
126b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        int visibility;
127b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        if (forcedVisibility != -1) {
128b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            visibility = forcedVisibility;
129b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        } else {
130b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            visibility = transitionValues.view.getVisibility();
131b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        }
132d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
133d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
134d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        int[] loc = new int[2];
135d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        transitionValues.view.getLocationOnScreen(loc);
136d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
137d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
138d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
139d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    @Override
140d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public void captureStartValues(TransitionValues transitionValues) {
141b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        captureValues(transitionValues, mForcedStartVisibility);
142d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
143d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
144199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    @Override
145d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public void captureEndValues(TransitionValues transitionValues) {
146b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        captureValues(transitionValues, mForcedEndVisibility);
147b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    }
148b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
149b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    /** @hide */
150b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    @Override
151b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    public void forceVisibility(int visibility, boolean isStartValue) {
152b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        if (isStartValue) {
153b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            mForcedStartVisibility = visibility;
154b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        } else {
155b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            mForcedEndVisibility = visibility;
156b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        }
157faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
158faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
159199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
160199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns whether the view is 'visible' according to the given values
161199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * object. This is determined by testing the same properties in the values
162199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * object that are used to determine whether the object is appearing or
163199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * disappearing in the {@link
164d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)}
165199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * method. This method can be called by, for example, subclasses that want
166199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * to know whether the object is visible in the same way that Visibility
167199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * determines it for the actual animation.
168199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
169199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @param values The TransitionValues object that holds the information by
170199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * which visibility is determined.
171199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return True if the view reference by <code>values</code> is visible,
172199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * false otherwise.
173199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
174199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public boolean isVisible(TransitionValues values) {
175199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (values == null) {
176199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            return false;
177199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
178199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
179199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        View parent = (View) values.values.get(PROPNAME_PARENT);
180199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
181199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return visibility == View.VISIBLE && parent != null;
182199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
183199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1846ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
185faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
1867660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase        final VisibilityInfo visInfo = new VisibilityInfo();
1876ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        visInfo.visibilityChange = false;
1886ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        visInfo.fadeIn = false;
18931a217290cf376d0573fc36e21c8940987485019George Mount        if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
1906ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
19135a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase            visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
192faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1936ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.startVisibility = -1;
1946ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.startParent = null;
195faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
19631a217290cf376d0573fc36e21c8940987485019George Mount        if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
1976ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
19835a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase            visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
199faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
2006ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.endVisibility = -1;
2016ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.endParent = null;
202faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
203faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (startValues != null && endValues != null) {
2046ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            if (visInfo.startVisibility == visInfo.endVisibility &&
2056ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    visInfo.startParent == visInfo.endParent) {
2066ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                return visInfo;
207faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
2086ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                if (visInfo.startVisibility != visInfo.endVisibility) {
2096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    if (visInfo.startVisibility == View.VISIBLE) {
2106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = false;
2116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
2126ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    } else if (visInfo.endVisibility == View.VISIBLE) {
2136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = true;
2146ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
215faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
216faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    // no visibilityChange if going between INVISIBLE and GONE
2176ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                } else if (visInfo.startParent != visInfo.endParent) {
2186ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    if (visInfo.endParent == null) {
2196ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = false;
2206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
2216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    } else if (visInfo.startParent == null) {
2226ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = true;
2236ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
224faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
225faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
22779b2781aa763cbd770f690c16af4448139f37061George Mount        } else if (startValues == null && visInfo.endVisibility == View.VISIBLE) {
2286ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.fadeIn = true;
2296ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.visibilityChange = true;
23079b2781aa763cbd770f690c16af4448139f37061George Mount        } else if (endValues == null && visInfo.startVisibility == View.VISIBLE) {
2316ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.fadeIn = false;
2326ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.visibilityChange = true;
233faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2346ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return visInfo;
235faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
236faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
238d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
2406ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
24130da61d477bcb6cc7718f9516c444359352fe148George Mount        if (visInfo.visibilityChange
24230da61d477bcb6cc7718f9516c444359352fe148George Mount                && (visInfo.startParent != null || visInfo.endParent != null)) {
24330da61d477bcb6cc7718f9516c444359352fe148George Mount            if (visInfo.fadeIn) {
24430da61d477bcb6cc7718f9516c444359352fe148George Mount                return onAppear(sceneRoot, startValues, visInfo.startVisibility,
24530da61d477bcb6cc7718f9516c444359352fe148George Mount                        endValues, visInfo.endVisibility);
24630da61d477bcb6cc7718f9516c444359352fe148George Mount            } else {
24730da61d477bcb6cc7718f9516c444359352fe148George Mount                return onDisappear(sceneRoot, startValues, visInfo.startVisibility,
24830da61d477bcb6cc7718f9516c444359352fe148George Mount                        endValues, visInfo.endVisibility
24930da61d477bcb6cc7718f9516c444359352fe148George Mount                );
250faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return null;
253faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
254faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
255faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
256d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method calls
257d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
258d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Subclasses should override this method or
259d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
260d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * if they need to create an Animator when targets appear.
261d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The method should only be called by the Visibility class; it is
262d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
263faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
264d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy
265d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The target values in the start scene
266d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startVisibility The target visibility in the start scene
267d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The target values in the end scene
268d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endVisibility The target visibility in the end scene
269d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return An Animator to be started at the appropriate time in the
270d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
271d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
272faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
273d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator onAppear(ViewGroup sceneRoot,
2746ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues startValues, int startVisibility,
2756ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues endValues, int endVisibility) {
276ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount        if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
27718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount            return null;
27818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        }
279e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout        if (startValues == null) {
280e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            VisibilityInfo parentVisibilityInfo = null;
281e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            View endParent = (View) endValues.view.getParent();
282e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            TransitionValues startParentValues = getMatchedTransitionValues(endParent,
283e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout                                                                            false);
284e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            TransitionValues endParentValues = getTransitionValues(endParent, false);
285e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            parentVisibilityInfo =
286e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout                getVisibilityChangeInfo(startParentValues, endParentValues);
287e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            if (parentVisibilityInfo.visibilityChange) {
288e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout                return null;
289e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            }
290e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout        }
291d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return onAppear(sceneRoot, endValues.view, startValues, endValues);
292d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
293d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
294d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
295d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method returns a null Animator. Subclasses should
296d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * override this method to make targets appear with the desired transition. The
297d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * method should only be called from
298d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
299d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *
300d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param sceneRoot The root of the transition hierarchy
301d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param view The View to make appear. This will be in the target scene's View hierarchy and
302d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *             will be VISIBLE.
303d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param startValues The target values in the start scene
304d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param endValues The target values in the end scene
305d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return An Animator to be started at the appropriate time in the
306d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * overall transition for this scene change. A null value means no animation
307d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * should be run.
308d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
309d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
310d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            TransitionValues endValues) {
3112ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase        return null;
312faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
315d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Subclasses should override this method or
316d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}
317d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * if they need to create an Animator when targets disappear.
318d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The method should only be called by the Visibility class; it is
319d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
320d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * <p>
321d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method attempts to find a View to use to call
322d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)},
323d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * based on the situation of the View in the View hierarchy. For example,
324d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * if a View was simply removed from its parent, then the View will be added
325d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * into a {@link android.view.ViewGroupOverlay} and passed as the <code>view</code>
326d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
327d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE},
328d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * then it can be used as the <code>view</code> and the visibility will be changed
329d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * to {@link View#VISIBLE} for the duration of the animation. However, if a View
330d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * is in a hierarchy which is also altering its visibility, the situation can be
331d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * more complicated. In general, if a view that is no longer in the hierarchy in
332d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the end scene still has a parent (so its parent hierarchy was removed, but it
333d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * was not removed from its parent), then it will be left alone to avoid side-effects from
334d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * improperly removing it from its parent. The only exception to this is if
335d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int,
336d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * android.content.Context) created from a layout resource file}, then it is considered
337d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * safe to un-parent the starting scene view in order to make it disappear.</p>
3386ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     *
339d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy
340d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The target values in the start scene
341d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startVisibility The target visibility in the start scene
342d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The target values in the end scene
343d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endVisibility The target visibility in the end scene
344d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return An Animator to be started at the appropriate time in the
345d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
346d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
347faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
348d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator onDisappear(ViewGroup sceneRoot,
3496ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues startValues, int startVisibility,
3506ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues endValues, int endVisibility) {
351ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount        if ((mMode & MODE_OUT) != MODE_OUT) {
35218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount            return null;
35318ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        }
35418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
355d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View startView = (startValues != null) ? startValues.view : null;
356d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View endView = (endValues != null) ? endValues.view : null;
357d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View overlayView = null;
358d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View viewToKeep = null;
359d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (endView == null || endView.getParent() == null) {
360d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (endView != null) {
361d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // endView was removed from its parent - add it to the overlay
362d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                overlayView = endView;
363d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            } else if (startView != null) {
364d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // endView does not exist. Use startView only under certain
365d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // conditions, because placing a view in an overlay necessitates
366d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // it being removed from its current parent
367d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (startView.getParent() == null) {
368d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    // no parent - safe to use
369d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    overlayView = startView;
370d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                } else if (startView.getParent() instanceof View) {
371d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    View startParent = (View) startView.getParent();
37279b2781aa763cbd770f690c16af4448139f37061George Mount                    TransitionValues startParentValues = getTransitionValues(startParent, true);
3739f1ac3976ea3aa08c20c06fa6678e367e1ed424dGeorge Mount                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
3749f1ac3976ea3aa08c20c06fa6678e367e1ed424dGeorge Mount                            true);
37579b2781aa763cbd770f690c16af4448139f37061George Mount                    VisibilityInfo parentVisibilityInfo =
37679b2781aa763cbd770f690c16af4448139f37061George Mount                            getVisibilityChangeInfo(startParentValues, endParentValues);
37779b2781aa763cbd770f690c16af4448139f37061George Mount                    if (!parentVisibilityInfo.visibilityChange) {
37879b2781aa763cbd770f690c16af4448139f37061George Mount                        overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
37979b2781aa763cbd770f690c16af4448139f37061George Mount                                startParent);
380d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                    } else if (startParent.getParent() == null) {
381d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                        int id = startParent.getId();
382d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
383d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                                && mCanRemoveViews) {
384d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            // no parent, but its parent is unparented  but the parent
385d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            // hierarchy has been replaced by a new hierarchy with the same id
386d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            // and it is safe to un-parent startView
387d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            overlayView = startView;
388d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                        }
389d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
390d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
391d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
392d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        } else {
393d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            // visibility change
394d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (endVisibility == View.INVISIBLE) {
395d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                viewToKeep = endView;
396d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            } else {
397d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // Becoming GONE
398d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (startView == endView) {
399d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    viewToKeep = endView;
400d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                } else {
401d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    overlayView = startView;
402d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
403d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
404d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
405d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        final int finalVisibility = endVisibility;
406d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        final ViewGroup finalSceneRoot = sceneRoot;
407d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
408d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (overlayView != null) {
409d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            // TODO: Need to do this for general case of adding to overlay
410d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
411d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int screenX = screenLoc[0];
412d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int screenY = screenLoc[1];
413d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int[] loc = new int[2];
414d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            sceneRoot.getLocationOnScreen(loc);
415d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
416d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
417d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            sceneRoot.getOverlay().add(overlayView);
418d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
419d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (animator == null) {
420d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                sceneRoot.getOverlay().remove(overlayView);
421d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            } else {
422d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                final View finalOverlayView = overlayView;
423d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.addListener(new AnimatorListenerAdapter() {
424d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
425d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationEnd(Animator animation) {
426d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        finalSceneRoot.getOverlay().remove(finalOverlayView);
427d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
428d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                });
429d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
430d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return animator;
431d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
432d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
433d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (viewToKeep != null) {
434b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            int originalVisibility = -1;
435b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            final boolean isForcedVisibility = mForcedStartVisibility != -1 ||
436b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                    mForcedEndVisibility != -1;
437b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            if (!isForcedVisibility) {
438b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                originalVisibility = viewToKeep.getVisibility();
439b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                viewToKeep.setVisibility(View.VISIBLE);
440b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            }
441d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
442b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            if (animator != null) {
443d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                final View finalViewToKeep = viewToKeep;
444d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.addListener(new AnimatorListenerAdapter() {
445d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    boolean mCanceled = false;
446d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
447d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
448d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationPause(Animator animation) {
449b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                        if (!mCanceled && !isForcedVisibility) {
450d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                            finalViewToKeep.setVisibility(finalVisibility);
451d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        }
452d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
453d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
454d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
455d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationResume(Animator animation) {
456b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                        if (!mCanceled && !isForcedVisibility) {
457d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                            finalViewToKeep.setVisibility(View.VISIBLE);
458d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        }
459d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
460d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
461d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
462d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationCancel(Animator animation) {
463d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        mCanceled = true;
464d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
465d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
466d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
467d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationEnd(Animator animation) {
468d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        if (!mCanceled) {
469b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                            if (isForcedVisibility) {
470b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                                finalViewToKeep.setTransitionAlpha(0);
471b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                            } else {
472b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                                finalViewToKeep.setVisibility(finalVisibility);
473b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                            }
474d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        }
475d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
476d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                });
477b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            } else if (!isForcedVisibility) {
478b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                viewToKeep.setVisibility(originalVisibility);
479d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
480d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return animator;
481d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
482d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return null;
483d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
484d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
4854c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    @Override
4864c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
4874c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        if (oldValues == null && newValues == null) {
4884c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount            return false;
4894c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        }
490cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        if (oldValues != null && newValues != null &&
491cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount                newValues.values.containsKey(PROPNAME_VISIBILITY) !=
492cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount                        oldValues.values.containsKey(PROPNAME_VISIBILITY)) {
493cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            // The transition wasn't targeted in either the start or end, so it couldn't
494cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            // have changed.
495cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            return false;
496cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        }
497cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
4984c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE ||
499cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount                changeInfo.endVisibility == View.VISIBLE);
5004c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    }
5014c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount
502d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
503d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method returns a null Animator. Subclasses should
504d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * override this method to make targets disappear with the desired transition. The
505d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * method should only be called from
506d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
507d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *
508d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param sceneRoot The root of the transition hierarchy
509d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param view The View to make disappear. This will be in the target scene's View
510d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *             hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
511d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *             VISIBLE.
512d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param startValues The target values in the start scene
513d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param endValues The target values in the end scene
514d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return An Animator to be started at the appropriate time in the
515d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * overall transition for this scene change. A null value means no animation
516d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * should be run.
517d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
518d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
519d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            TransitionValues endValues) {
5206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return null;
5216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
522faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase}
523