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,
6620559079ab05aa5e976bb0f7aa63fd9e6868f02eGeorge Mount            PROPNAME_PARENT,
67199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    };
68faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
696ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private static class VisibilityInfo {
706ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        boolean visibilityChange;
716ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        boolean fadeIn;
726ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        int startVisibility;
736ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        int endVisibility;
7435a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase        ViewGroup startParent;
7535a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase        ViewGroup endParent;
766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
776ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase
78ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount    private int mMode = MODE_IN | MODE_OUT;
7918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
80b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    private int mForcedStartVisibility = -1;
81b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    private int mForcedEndVisibility = -1;
82b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
83ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public Visibility() {}
84ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
85ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public Visibility(Context context, AttributeSet attrs) {
86ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        super(context, attrs);
87ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition);
883b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner        int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0);
89ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        a.recycle();
90ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        if (mode != 0) {
91ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount            setMode(mode);
92ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        }
93ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
94ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
9518ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    /**
9618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * Changes the transition to support appearing and/or disappearing Views, depending
9718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * on <code>mode</code>.
9818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     *
9918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     * @param mode The behavior supported by this transition, a combination of
100ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount     *             {@link #MODE_IN} and {@link #MODE_OUT}.
1013b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner     * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
10218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount     */
10318ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    public void setMode(int mode) {
104ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount        if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
105ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount            throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
10618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        }
10718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        mMode = mode;
10818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount    }
10918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
110ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    /**
111ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Returns whether appearing and/or disappearing Views are supported.
112ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     *
113ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     * Returns whether appearing and/or disappearing Views are supported. A combination of
114ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount     *         {@link #MODE_IN} and {@link #MODE_OUT}.
1153b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner     * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
116ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount     */
117ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    public int getMode() {
118ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount        return mMode;
119ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount    }
120ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount
121faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
122199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public String[] getTransitionProperties() {
123199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return sTransitionProperties;
124199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
125199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
126b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    private void captureValues(TransitionValues transitionValues, int forcedVisibility) {
127b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        int visibility;
128b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        if (forcedVisibility != -1) {
129b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            visibility = forcedVisibility;
130b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        } else {
131b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            visibility = transitionValues.view.getVisibility();
132b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        }
133d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
134d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase        transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
135d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        int[] loc = new int[2];
136d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        transitionValues.view.getLocationOnScreen(loc);
137d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
138d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
139d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
140d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    @Override
141d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public void captureStartValues(TransitionValues transitionValues) {
142b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        captureValues(transitionValues, mForcedStartVisibility);
143d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    }
144d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase
145199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    @Override
146d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public void captureEndValues(TransitionValues transitionValues) {
147b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        captureValues(transitionValues, mForcedEndVisibility);
148b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    }
149b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount
150b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    /** @hide */
151b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    @Override
152b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount    public void forceVisibility(int visibility, boolean isStartValue) {
153b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        if (isStartValue) {
154b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            mForcedStartVisibility = visibility;
155b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        } else {
156b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            mForcedEndVisibility = visibility;
157b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount        }
158faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
159faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
160199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    /**
161199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * Returns whether the view is 'visible' according to the given values
162199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * object. This is determined by testing the same properties in the values
163199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * object that are used to determine whether the object is appearing or
164199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * disappearing in the {@link
165d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)}
166199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * method. This method can be called by, for example, subclasses that want
167199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * to know whether the object is visible in the same way that Visibility
168199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * determines it for the actual animation.
169199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     *
170199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @param values The TransitionValues object that holds the information by
171199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * which visibility is determined.
172199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * @return True if the view reference by <code>values</code> is visible,
173199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     * false otherwise.
174199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase     */
175199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    public boolean isVisible(TransitionValues values) {
176199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        if (values == null) {
177199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase            return false;
178199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        }
179199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
180199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        View parent = (View) values.values.get(PROPNAME_PARENT);
181199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
182199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase        return visibility == View.VISIBLE && parent != null;
183199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase    }
184199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase
1856ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
186faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
1877660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase        final VisibilityInfo visInfo = new VisibilityInfo();
1886ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        visInfo.visibilityChange = false;
1896ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        visInfo.fadeIn = false;
19031a217290cf376d0573fc36e21c8940987485019George Mount        if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
1916ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
19235a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase            visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
193faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
1946ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.startVisibility = -1;
1956ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.startParent = null;
196faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
19731a217290cf376d0573fc36e21c8940987485019George Mount        if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
1986ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
19935a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase            visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
200faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        } else {
2016ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.endVisibility = -1;
2026ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.endParent = null;
203faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
204faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        if (startValues != null && endValues != null) {
2056ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            if (visInfo.startVisibility == visInfo.endVisibility &&
2066ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    visInfo.startParent == visInfo.endParent) {
2076ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                return visInfo;
208faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            } else {
2096ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                if (visInfo.startVisibility != visInfo.endVisibility) {
2106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    if (visInfo.startVisibility == View.VISIBLE) {
2116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = false;
2126ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
2136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    } else if (visInfo.endVisibility == View.VISIBLE) {
2146ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = true;
2156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
216faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
217faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    // no visibilityChange if going between INVISIBLE and GONE
2186ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                } else if (visInfo.startParent != visInfo.endParent) {
2196ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    if (visInfo.endParent == null) {
2206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = false;
2216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
2226ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                    } else if (visInfo.startParent == null) {
2236ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.fadeIn = true;
2246ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase                        visInfo.visibilityChange = true;
225faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                    }
226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase                }
227faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
22879b2781aa763cbd770f690c16af4448139f37061George Mount        } else if (startValues == null && visInfo.endVisibility == View.VISIBLE) {
2296ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.fadeIn = true;
2306ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.visibilityChange = true;
23179b2781aa763cbd770f690c16af4448139f37061George Mount        } else if (endValues == null && visInfo.startVisibility == View.VISIBLE) {
2326ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.fadeIn = false;
2336ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            visInfo.visibilityChange = true;
234faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
2356ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return visInfo;
236faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
238faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    @Override
239d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
240faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            TransitionValues endValues) {
2416ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
24230da61d477bcb6cc7718f9516c444359352fe148George Mount        if (visInfo.visibilityChange
24330da61d477bcb6cc7718f9516c444359352fe148George Mount                && (visInfo.startParent != null || visInfo.endParent != null)) {
24430da61d477bcb6cc7718f9516c444359352fe148George Mount            if (visInfo.fadeIn) {
24530da61d477bcb6cc7718f9516c444359352fe148George Mount                return onAppear(sceneRoot, startValues, visInfo.startVisibility,
24630da61d477bcb6cc7718f9516c444359352fe148George Mount                        endValues, visInfo.endVisibility);
24730da61d477bcb6cc7718f9516c444359352fe148George Mount            } else {
24830da61d477bcb6cc7718f9516c444359352fe148George Mount                return onDisappear(sceneRoot, startValues, visInfo.startVisibility,
24930da61d477bcb6cc7718f9516c444359352fe148George Mount                        endValues, visInfo.endVisibility
25030da61d477bcb6cc7718f9516c444359352fe148George Mount                );
251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase            }
252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        }
253faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase        return null;
254faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
255faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
256faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
257d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method calls
258d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
259d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Subclasses should override this method or
260d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
261d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * if they need to create an Animator when targets appear.
262d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The method should only be called by the Visibility class; it is
263d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
264faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     *
265d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy
266d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The target values in the start scene
267d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startVisibility The target visibility in the start scene
268d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The target values in the end scene
269d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endVisibility The target visibility in the end scene
270d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return An Animator to be started at the appropriate time in the
271d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
272d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
273faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
274d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator onAppear(ViewGroup sceneRoot,
2756ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues startValues, int startVisibility,
2766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues endValues, int endVisibility) {
277ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount        if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
27818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount            return null;
27918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        }
280e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout        if (startValues == null) {
281e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            VisibilityInfo parentVisibilityInfo = null;
282e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            View endParent = (View) endValues.view.getParent();
283e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            TransitionValues startParentValues = getMatchedTransitionValues(endParent,
284e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout                                                                            false);
285e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            TransitionValues endParentValues = getTransitionValues(endParent, false);
286e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            parentVisibilityInfo =
287e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout                getVisibilityChangeInfo(startParentValues, endParentValues);
288e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            if (parentVisibilityInfo.visibilityChange) {
289e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout                return null;
290e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout            }
291e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout        }
292d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return onAppear(sceneRoot, endValues.view, startValues, endValues);
293d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
294d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
295d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
296d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method returns a null Animator. Subclasses should
297d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * override this method to make targets appear with the desired transition. The
298d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * method should only be called from
299d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
300d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *
301d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param sceneRoot The root of the transition hierarchy
302d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param view The View to make appear. This will be in the target scene's View hierarchy and
303d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *             will be VISIBLE.
304d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param startValues The target values in the start scene
305d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param endValues The target values in the end scene
306d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return An Animator to be started at the appropriate time in the
307d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * overall transition for this scene change. A null value means no animation
308d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * should be run.
309d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
310d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
311d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            TransitionValues endValues) {
3122ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase        return null;
313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    }
314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase
315faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase    /**
316d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * Subclasses should override this method or
317d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}
318d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * if they need to create an Animator when targets disappear.
319d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * The method should only be called by the Visibility class; it is
320d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * not intended to be called from external classes.
321d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * <p>
322d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method attempts to find a View to use to call
323d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)},
324d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * based on the situation of the View in the View hierarchy. For example,
325d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * if a View was simply removed from its parent, then the View will be added
326d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * into a {@link android.view.ViewGroupOverlay} and passed as the <code>view</code>
327d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
328d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE},
329d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * then it can be used as the <code>view</code> and the visibility will be changed
330d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * to {@link View#VISIBLE} for the duration of the animation. However, if a View
331d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * is in a hierarchy which is also altering its visibility, the situation can be
332d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * more complicated. In general, if a view that is no longer in the hierarchy in
333d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the end scene still has a parent (so its parent hierarchy was removed, but it
334d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * was not removed from its parent), then it will be left alone to avoid side-effects from
335d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * improperly removing it from its parent. The only exception to this is if
336d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int,
337d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * android.content.Context) created from a layout resource file}, then it is considered
338d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * safe to un-parent the starting scene view in order to make it disappear.</p>
3396ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase     *
340d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param sceneRoot The root of the transition hierarchy
341d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startValues The target values in the start scene
342d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param startVisibility The target visibility in the start scene
343d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endValues The target values in the end scene
344d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @param endVisibility The target visibility in the end scene
345d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * @return An Animator to be started at the appropriate time in the
346d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * overall transition for this scene change. A null value means no animation
347d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase     * should be run.
348faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase     */
349d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase    public Animator onDisappear(ViewGroup sceneRoot,
3506ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues startValues, int startVisibility,
3516ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase            TransitionValues endValues, int endVisibility) {
352ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount        if ((mMode & MODE_OUT) != MODE_OUT) {
35318ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount            return null;
35418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount        }
35518ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount
356d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View startView = (startValues != null) ? startValues.view : null;
357d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View endView = (endValues != null) ? endValues.view : null;
358d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View overlayView = null;
359d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        View viewToKeep = null;
360d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (endView == null || endView.getParent() == null) {
361d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (endView != null) {
362d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // endView was removed from its parent - add it to the overlay
363d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                overlayView = endView;
364d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            } else if (startView != null) {
365d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // endView does not exist. Use startView only under certain
366d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // conditions, because placing a view in an overlay necessitates
367d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // it being removed from its current parent
368d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (startView.getParent() == null) {
369d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    // no parent - safe to use
370d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    overlayView = startView;
371d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                } else if (startView.getParent() instanceof View) {
372d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    View startParent = (View) startView.getParent();
37379b2781aa763cbd770f690c16af4448139f37061George Mount                    TransitionValues startParentValues = getTransitionValues(startParent, true);
3749f1ac3976ea3aa08c20c06fa6678e367e1ed424dGeorge Mount                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
3759f1ac3976ea3aa08c20c06fa6678e367e1ed424dGeorge Mount                            true);
37679b2781aa763cbd770f690c16af4448139f37061George Mount                    VisibilityInfo parentVisibilityInfo =
37779b2781aa763cbd770f690c16af4448139f37061George Mount                            getVisibilityChangeInfo(startParentValues, endParentValues);
37879b2781aa763cbd770f690c16af4448139f37061George Mount                    if (!parentVisibilityInfo.visibilityChange) {
37979b2781aa763cbd770f690c16af4448139f37061George Mount                        overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
38079b2781aa763cbd770f690c16af4448139f37061George Mount                                startParent);
381d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                    } else if (startParent.getParent() == null) {
382d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                        int id = startParent.getId();
383d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
384d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                                && mCanRemoveViews) {
385d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            // no parent, but its parent is unparented  but the parent
386d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            // hierarchy has been replaced by a new hierarchy with the same id
387d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            // and it is safe to un-parent startView
388d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                            overlayView = startView;
389d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount                        }
390d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
391d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
392d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
393d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        } else {
394d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            // visibility change
395d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (endVisibility == View.INVISIBLE) {
396d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                viewToKeep = endView;
397d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            } else {
398d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                // Becoming GONE
399d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                if (startView == endView) {
400d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    viewToKeep = endView;
401d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                } else {
402d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    overlayView = startView;
403d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                }
404d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
405d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
406d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        final int finalVisibility = endVisibility;
407d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        final ViewGroup finalSceneRoot = sceneRoot;
408d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
409d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (overlayView != null) {
410d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            // TODO: Need to do this for general case of adding to overlay
411d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
412d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int screenX = screenLoc[0];
413d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int screenY = screenLoc[1];
414d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            int[] loc = new int[2];
415d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            sceneRoot.getLocationOnScreen(loc);
416d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
417d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
418d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            sceneRoot.getOverlay().add(overlayView);
419d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
420d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            if (animator == null) {
421d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                sceneRoot.getOverlay().remove(overlayView);
422d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            } else {
423d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                final View finalOverlayView = overlayView;
424d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.addListener(new AnimatorListenerAdapter() {
425d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
426d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationEnd(Animator animation) {
427d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        finalSceneRoot.getOverlay().remove(finalOverlayView);
428d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
429d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                });
430d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
431d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return animator;
432d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
433d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
434d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        if (viewToKeep != null) {
435b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            int originalVisibility = -1;
436b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            final boolean isForcedVisibility = mForcedStartVisibility != -1 ||
437b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                    mForcedEndVisibility != -1;
438b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            if (!isForcedVisibility) {
439b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                originalVisibility = viewToKeep.getVisibility();
440b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                viewToKeep.setVisibility(View.VISIBLE);
441b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            }
442d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
443b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            if (animator != null) {
444d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                final View finalViewToKeep = viewToKeep;
445d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                animator.addListener(new AnimatorListenerAdapter() {
446d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    boolean mCanceled = false;
447d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
448d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
449d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationPause(Animator animation) {
450b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                        if (!mCanceled && !isForcedVisibility) {
451d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                            finalViewToKeep.setVisibility(finalVisibility);
452d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        }
453d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
454d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
455d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
456d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationResume(Animator animation) {
457b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                        if (!mCanceled && !isForcedVisibility) {
458d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                            finalViewToKeep.setVisibility(View.VISIBLE);
459d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        }
460d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
461d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
462d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
463d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationCancel(Animator animation) {
464d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        mCanceled = true;
465d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
466d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
467d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    @Override
468d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    public void onAnimationEnd(Animator animation) {
469d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        if (!mCanceled) {
470b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                            if (isForcedVisibility) {
471b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                                finalViewToKeep.setTransitionAlpha(0);
472b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                            } else {
473b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                                finalViewToKeep.setVisibility(finalVisibility);
474b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                            }
475d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                        }
476d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                    }
477d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount                });
478b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount            } else if (!isForcedVisibility) {
479b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount                viewToKeep.setVisibility(originalVisibility);
480d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            }
481d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            return animator;
482d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        }
483d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount        return null;
484d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    }
485d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount
4864c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    @Override
4874c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
4884c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        if (oldValues == null && newValues == null) {
4894c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount            return false;
4904c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        }
491cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        if (oldValues != null && newValues != null &&
492cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount                newValues.values.containsKey(PROPNAME_VISIBILITY) !=
493cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount                        oldValues.values.containsKey(PROPNAME_VISIBILITY)) {
494cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            // The transition wasn't targeted in either the start or end, so it couldn't
495cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            // have changed.
496cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount            return false;
497cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        }
498cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount        VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
4994c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount        return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE ||
500cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount                changeInfo.endVisibility == View.VISIBLE);
5014c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount    }
5024c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount
503d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    /**
504d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * The default implementation of this method returns a null Animator. Subclasses should
505d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * override this method to make targets disappear with the desired transition. The
506d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * method should only be called from
507d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
508d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *
509d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param sceneRoot The root of the transition hierarchy
510d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param view The View to make disappear. This will be in the target scene's View
511d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *             hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
512d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     *             VISIBLE.
513d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param startValues The target values in the start scene
514d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @param endValues The target values in the end scene
515d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * @return An Animator to be started at the appropriate time in the
516d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * overall transition for this scene change. A null value means no animation
517d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     * should be run.
518d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount     */
519d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount    public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
520d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount            TransitionValues endValues) {
5216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase        return null;
5226ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase    }
523faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase}
524