Visibility.java revision 4c904b38c763179727b9b5ea7a80454630545663
1733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki/*
2733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * Copyright (C) 2016 The Android Open Source Project
3733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki *
4733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License");
5733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * you may not use this file except in compliance with the License.
6733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * You may obtain a copy of the License at
7733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki *
8733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki *      http://www.apache.org/licenses/LICENSE-2.0
9733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki *
10733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * Unless required by applicable law or agreed to in writing, software
11733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS,
12733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * See the License for the specific language governing permissions and
14733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * limitations under the License.
15733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki */
16733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
17733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Arakipackage android.support.transition;
18733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
19a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Arakiimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
21733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Arakiimport android.animation.Animator;
22a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Arakiimport android.animation.AnimatorListenerAdapter;
238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.Context;
248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.TypedArray;
258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.XmlResourceParser;
26a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Arakiimport android.support.annotation.IntDef;
27733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Arakiimport android.support.annotation.NonNull;
284e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport android.support.annotation.Nullable;
29a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Arakiimport android.support.annotation.RestrictTo;
308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.support.v4.content.res.TypedArrayUtils;
318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.util.AttributeSet;
32733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Arakiimport android.view.View;
33733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Arakiimport android.view.ViewGroup;
34733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
35a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Arakiimport java.lang.annotation.Retention;
36a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Arakiimport java.lang.annotation.RetentionPolicy;
37a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
38733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki/**
39733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * This transition tracks changes to the visibility of target views in the
40733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * start and end scenes. Visibility is determined not just by the
41733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * {@link View#setVisibility(int)} state of views, but also whether
42733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * views exist in the current view hierarchy. The class is intended to be a
439562a3b639225d406d736b64a12e2d75459259e3Alan Viverette * utility for subclasses such as {@link Fade}, which use this visibility
44733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * information to determine the specific animations to run when visibility
45733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * changes occur. Subclasses should implement one or both of the methods
46733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
478158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
488158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
498158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
50733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki */
514e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakipublic abstract class Visibility extends Transition {
52733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
534c904b38c763179727b9b5ea7a80454630545663Yuichi Araki    static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static final String PROPNAME_PARENT = "android:visibility:parent";
55a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
56a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
57a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /**
58a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * Mode used in {@link #setMode(int)} to make the transition
59a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * operate on targets that are appearing. Maybe be combined with
60a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * {@link #MODE_OUT} to target Visibility changes both in and out.
61a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     */
62a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public static final int MODE_IN = 0x1;
63a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
64a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /**
65a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * Mode used in {@link #setMode(int)} to make the transition
66a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * operate on targets that are disappearing. Maybe be combined with
67a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * {@link #MODE_IN} to target Visibility changes both in and out.
68a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     */
69a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public static final int MODE_OUT = 0x2;
70a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
71a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /** @hide */
72a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    @RestrictTo(LIBRARY_GROUP)
73a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    @IntDef(flag = true, value = {MODE_IN, MODE_OUT})
74a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    @Retention(RetentionPolicy.SOURCE)
75a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public @interface Mode {
76a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    }
774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static final String[] sTransitionProperties = {
794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            PROPNAME_VISIBILITY,
804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            PROPNAME_PARENT,
814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    };
824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private static class VisibilityInfo {
844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        boolean mVisibilityChange;
854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        boolean mFadeIn;
864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        int mStartVisibility;
874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        int mEndVisibility;
884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ViewGroup mStartParent;
894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ViewGroup mEndParent;
90733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
91733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
92a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    private int mMode = MODE_IN | MODE_OUT;
93a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Visibility() {
95733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
96733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    public Visibility(Context context, AttributeSet attrs) {
988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        super(context, attrs);
998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        TypedArray a = context.obtainStyledAttributes(attrs, Styleable.VISIBILITY_TRANSITION);
1008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        @Mode
1018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        int mode = TypedArrayUtils.getNamedInt(a, (XmlResourceParser) attrs,
1028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                "transitionVisibilityMode",
1038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki                Styleable.VisibilityTransition.TRANSITION_VISIBILITY_MODE, 0);
1048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        a.recycle();
1058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        if (mode != 0) {
1068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki            setMode(mode);
1078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki        }
1088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki    }
1098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki
110a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /**
111a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * Changes the transition to support appearing and/or disappearing Views, depending
112a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * on <code>mode</code>.
113a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *
114a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param mode The behavior supported by this transition, a combination of
115a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *             {@link #MODE_IN} and {@link #MODE_OUT}.
116a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     */
117a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public void setMode(@Mode int mode) {
118a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
119a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed");
120a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
121a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        mMode = mode;
122a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    }
123a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
124a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /**
125a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * Returns whether appearing and/or disappearing Views are supported.
126a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *
127a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @return whether appearing and/or disappearing Views are supported. A combination of
128a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * {@link #MODE_IN} and {@link #MODE_OUT}.
129a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     */
130a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    @Mode
131a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public int getMode() {
132a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        return mMode;
133a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    }
134a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
1354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Nullable
136733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    @Override
1374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public String[] getTransitionProperties() {
1384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return sTransitionProperties;
1394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
1404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private void captureValues(TransitionValues transitionValues) {
1424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        int visibility = transitionValues.view.getVisibility();
1434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
1444e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
145a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        int[] loc = new int[2];
146a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        transitionValues.view.getLocationOnScreen(loc);
147a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
148733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
149733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
150733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    @Override
151733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    public void captureStartValues(@NonNull TransitionValues transitionValues) {
1524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        captureValues(transitionValues);
1534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
1544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
1564e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public void captureEndValues(@NonNull TransitionValues transitionValues) {
1574e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        captureValues(transitionValues);
158733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
159733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
160733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    /**
161733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * Returns whether the view is 'visible' according to the given values
162733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * object. This is determined by testing the same properties in the values
163733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * object that are used to determine whether the object is appearing or
164733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * disappearing in the {@link
165733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)}
166733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * method. This method can be called by, for example, subclasses that want
167733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * to know whether the object is visible in the same way that Visibility
168733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * determines it for the actual animation.
169733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     *
170733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param values The TransitionValues object that holds the information by
171733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     *               which visibility is determined.
172733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @return True if the view reference by <code>values</code> is visible,
173733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * false otherwise.
174733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     */
175733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    public boolean isVisible(TransitionValues values) {
1764e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (values == null) {
1774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return false;
1784e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
1794e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
1804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        View parent = (View) values.values.get(PROPNAME_PARENT);
1814e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1824e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return visibility == View.VISIBLE && parent != null;
1834e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
1844e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
1854e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
1864e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            TransitionValues endValues) {
1874e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        final VisibilityInfo visInfo = new VisibilityInfo();
1884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        visInfo.mVisibilityChange = false;
1894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        visInfo.mFadeIn = false;
190a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
1914e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mStartVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
1924e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mStartParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
1934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        } else {
1944e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mStartVisibility = -1;
1954e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mStartParent = null;
1964e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
197a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
1984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mEndVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
1994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mEndParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
2004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        } else {
2014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mEndVisibility = -1;
2024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mEndParent = null;
2034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
2044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        if (startValues != null && endValues != null) {
2054e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (visInfo.mStartVisibility == visInfo.mEndVisibility
2064e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    && visInfo.mStartParent == visInfo.mEndParent) {
2074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                return visInfo;
2084e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            } else {
2094e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (visInfo.mStartVisibility != visInfo.mEndVisibility) {
2104e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (visInfo.mStartVisibility == View.VISIBLE) {
2114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mFadeIn = false;
2124e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mVisibilityChange = true;
2134e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    } else if (visInfo.mEndVisibility == View.VISIBLE) {
2144e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mFadeIn = true;
2154e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mVisibilityChange = true;
2164e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
2174e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    // no visibilityChange if going between INVISIBLE and GONE
2184e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                } else /* if (visInfo.mStartParent != visInfo.mEndParent) */ {
2194e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    if (visInfo.mEndParent == null) {
2204e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mFadeIn = false;
2214e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mVisibilityChange = true;
2224e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    } else if (visInfo.mStartParent == null) {
2234e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mFadeIn = true;
2244e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        visInfo.mVisibilityChange = true;
2254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    }
2264e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                }
2274e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
228a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        } else if (startValues == null && visInfo.mEndVisibility == View.VISIBLE) {
2294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mFadeIn = true;
2304e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mVisibilityChange = true;
231a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        } else if (endValues == null && visInfo.mStartVisibility == View.VISIBLE) {
2324e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mFadeIn = false;
2334e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            visInfo.mVisibilityChange = true;
2344e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
2354e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return visInfo;
2364e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
2374e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
2384e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Nullable
2394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
2404e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public Animator createAnimator(@NonNull ViewGroup sceneRoot,
2414e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            @Nullable TransitionValues startValues, @Nullable TransitionValues endValues) {
2424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
243a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (visInfo.mVisibilityChange
244a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                && (visInfo.mStartParent != null || visInfo.mEndParent != null)) {
245a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            if (visInfo.mFadeIn) {
246a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                return onAppear(sceneRoot, startValues, visInfo.mStartVisibility,
247a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        endValues, visInfo.mEndVisibility);
248a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            } else {
249a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                return onDisappear(sceneRoot, startValues, visInfo.mStartVisibility,
250a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        endValues, visInfo.mEndVisibility
251a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                );
2524e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            }
2534e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        }
2544e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return null;
255733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
256733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
257733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    /**
258733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * The default implementation of this method does nothing. Subclasses
259733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * should override if they need to create an Animator when targets appear.
260733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * The method should only be called by the Visibility class; it is
261733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * not intended to be called from external classes.
262733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     *
263733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param sceneRoot       The root of the transition hierarchy
264733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param startValues     The target values in the start scene
265733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param startVisibility The target visibility in the start scene
266733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param endValues       The target values in the end scene
267733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param endVisibility   The target visibility in the end scene
268733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @return An Animator to be started at the appropriate time in the
269733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * overall transition for this scene change. A null value means no animation
270733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * should be run.
271733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     */
2724e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @SuppressWarnings("UnusedParameters")
273733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues, int startVisibility,
274733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki            TransitionValues endValues, int endVisibility) {
275a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if ((mMode & MODE_IN) != MODE_IN || endValues == null) {
276a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            return null;
277a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
278a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (startValues == null) {
279a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            View endParent = (View) endValues.view.getParent();
280a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            TransitionValues startParentValues = getMatchedTransitionValues(endParent,
281a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    false);
282a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            TransitionValues endParentValues = getTransitionValues(endParent, false);
283a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            VisibilityInfo parentVisibilityInfo =
284a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    getVisibilityChangeInfo(startParentValues, endParentValues);
285a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            if (parentVisibilityInfo.mVisibilityChange) {
286a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                return null;
287a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            }
288a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
289a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        return onAppear(sceneRoot, endValues.view, startValues, endValues);
290a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    }
291a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
292a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /**
293a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * The default implementation of this method returns a null Animator. Subclasses should
294a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * override this method to make targets appear with the desired transition. The
295a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * method should only be called from
296a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
297a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *
298a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param sceneRoot   The root of the transition hierarchy
299a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param view        The View to make appear. This will be in the target scene's View
300a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *                    hierarchy
301a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *                    and
302a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *                    will be VISIBLE.
303a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param startValues The target values in the start scene
304a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param endValues   The target values in the end scene
305a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @return An Animator to be started at the appropriate time in the
306a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * overall transition for this scene change. A null value means no animation
307a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * should be run.
308a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     */
309a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
310a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            TransitionValues endValues) {
3114e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return null;
312733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
313733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
314733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    /**
315733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * The default implementation of this method does nothing. Subclasses
316733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * should override if they need to create an Animator when targets disappear.
317733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * The method should only be called by the Visibility class; it is
318733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * not intended to be called from external classes.
319733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     *
320733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param sceneRoot       The root of the transition hierarchy
321733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param startValues     The target values in the start scene
322733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param startVisibility The target visibility in the start scene
323733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param endValues       The target values in the end scene
324733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @param endVisibility   The target visibility in the end scene
325733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * @return An Animator to be started at the appropriate time in the
326733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * overall transition for this scene change. A null value means no animation
327733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     * should be run.
328733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki     */
3294e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @SuppressWarnings("UnusedParameters")
330733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    public Animator onDisappear(ViewGroup sceneRoot, TransitionValues startValues,
331733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki            int startVisibility, TransitionValues endValues, int endVisibility) {
332a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if ((mMode & MODE_OUT) != MODE_OUT) {
333a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            return null;
334a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
335a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
336a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        View startView = (startValues != null) ? startValues.view : null;
337a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        View endView = (endValues != null) ? endValues.view : null;
338a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        View overlayView = null;
339a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        View viewToKeep = null;
340a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (endView == null || endView.getParent() == null) {
341a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            if (endView != null) {
342a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                // endView was removed from its parent - add it to the overlay
343a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                overlayView = endView;
344a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            } else if (startView != null) {
345a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                // endView does not exist. Use startView only under certain
346a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                // conditions, because placing a view in an overlay necessitates
347a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                // it being removed from its current parent
348a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                if (startView.getParent() == null) {
349a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    // no parent - safe to use
350a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    overlayView = startView;
351a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                } else if (startView.getParent() instanceof View) {
352a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    View startParent = (View) startView.getParent();
353a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    TransitionValues startParentValues = getTransitionValues(startParent, true);
354a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
355a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            true);
356a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    VisibilityInfo parentVisibilityInfo =
357a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            getVisibilityChangeInfo(startParentValues, endParentValues);
358a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    if (!parentVisibilityInfo.mVisibilityChange) {
359a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
360a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                                startParent);
361a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    } else if (startParent.getParent() == null) {
362a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        int id = startParent.getId();
363a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
364a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                                && mCanRemoveViews) {
365a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            // no parent, but its parent is unparented  but the parent
366a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            // hierarchy has been replaced by a new hierarchy with the same id
367a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            // and it is safe to un-parent startView
368a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            overlayView = startView;
369a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        }
370a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    }
371a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                }
372a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            }
373a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        } else {
374a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            // visibility change
375a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            if (endVisibility == View.INVISIBLE) {
376a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                viewToKeep = endView;
377a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            } else {
378a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                // Becoming GONE
379a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                if (startView == endView) {
380a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    viewToKeep = endView;
381a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                } else {
382a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    overlayView = startView;
383a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                }
384a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            }
385a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
386a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        final int finalVisibility = endVisibility;
387a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
388a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (overlayView != null && startValues != null) {
389a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            // TODO: Need to do this for general case of adding to overlay
390a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
391a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            int screenX = screenLoc[0];
392a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            int screenY = screenLoc[1];
393a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            int[] loc = new int[2];
394a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            sceneRoot.getLocationOnScreen(loc);
395a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
396a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
397a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            final ViewGroupOverlayImpl overlay = ViewGroupUtils.getOverlay(sceneRoot);
398a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            overlay.add(overlayView);
399a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
400a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            if (animator == null) {
401a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                overlay.remove(overlayView);
402a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            } else {
403a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                final View finalOverlayView = overlayView;
404a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                animator.addListener(new AnimatorListenerAdapter() {
405a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    @Override
406a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    public void onAnimationEnd(Animator animation) {
407a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        overlay.remove(finalOverlayView);
408a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    }
409a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                });
410a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            }
411a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            return animator;
412a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
413a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
414a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        if (viewToKeep != null) {
415a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            int originalVisibility = -1;
416a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            originalVisibility = viewToKeep.getVisibility();
417a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            viewToKeep.setVisibility(View.VISIBLE);
418a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
419a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            if (animator != null) {
420a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                final View finalViewToKeep = viewToKeep;
421a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                animator.addListener(new AnimatorListenerAdapter() {
422a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    boolean mCanceled = false;
423a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
424a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    @Override
425a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    public void onAnimationPause(Animator animation) {
426a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        if (!mCanceled) {
427a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            //noinspection WrongConstant
428a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            finalViewToKeep.setVisibility(finalVisibility);
429a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        }
430a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    }
431a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
432a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    @Override
433a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    public void onAnimationResume(Animator animation) {
434a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        if (!mCanceled) {
435a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            finalViewToKeep.setVisibility(View.VISIBLE);
436a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        }
437a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    }
438a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
439a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    @Override
440a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    public void onAnimationCancel(Animator animation) {
441a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        mCanceled = true;
442a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    }
443a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
444a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    @Override
445a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    public void onAnimationEnd(Animator animation) {
446a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        if (!mCanceled) {
447a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            //noinspection WrongConstant
448a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                            finalViewToKeep.setVisibility(finalVisibility);
449a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                        }
450a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                    }
451a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                });
452a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            } else {
453a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki                viewToKeep.setVisibility(originalVisibility);
454a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            }
455a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            return animator;
456a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        }
457a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki        return null;
458a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
459a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
460a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    }
461a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki
462a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    /**
463a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * The default implementation of this method returns a null Animator. Subclasses should
464a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * override this method to make targets disappear with the desired transition. The
465a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * method should only be called from
466a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
467a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *
468a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param sceneRoot   The root of the transition hierarchy
469a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param view        The View to make disappear. This will be in the target scene's View
470a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *                    hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
471a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     *                    VISIBLE.
472a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param startValues The target values in the start scene
473a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @param endValues   The target values in the end scene
474a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * @return An Animator to be started at the appropriate time in the
475a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * overall transition for this scene change. A null value means no animation
476a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     * should be run.
477a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki     */
478a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki    public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
479a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki            TransitionValues endValues) {
4804e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        return null;
481733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    }
482733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
483756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    @Override
484756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
485756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        if (oldValues == null && newValues == null) {
486756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki            return false;
487756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        }
488756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
489756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki        return changeInfo.mVisibilityChange && (changeInfo.mStartVisibility == View.VISIBLE
490756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki                || changeInfo.mEndVisibility == View.VISIBLE);
491756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki    }
492756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki
493733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki    // TODO: Implement API 23; isTransitionRequired
494733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki
495733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki}
496