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) { 415ce318dbf0020462e651049fd4f32dc226b656f5bAurimas Liutikas int originalVisibility = viewToKeep.getVisibility(); 416928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ViewUtils.setTransitionVisibility(viewToKeep, View.VISIBLE); 417a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues); 418a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki if (animator != null) { 419928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki DisappearListener disappearListener = new DisappearListener(viewToKeep, 420928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki finalVisibility, true); 421928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki animator.addListener(disappearListener); 422928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki AnimatorUtils.addPauseListener(animator, disappearListener); 423928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki addListener(disappearListener); 424a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki } else { 425928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ViewUtils.setTransitionVisibility(viewToKeep, originalVisibility); 426a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki } 427a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki return animator; 428a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki } 429a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki return null; 430a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki } 431a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki 432a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki /** 433a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * The default implementation of this method returns a null Animator. Subclasses should 434a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * override this method to make targets disappear with the desired transition. The 435a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * method should only be called from 436a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}. 437a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * 438a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * @param sceneRoot The root of the transition hierarchy 439a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * @param view The View to make disappear. This will be in the target scene's View 440a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * hierarchy or in an {@link android.view.ViewGroupOverlay} and will be 441a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * VISIBLE. 442a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * @param startValues The target values in the start scene 443a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * @param endValues The target values in the end scene 444a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * @return An Animator to be started at the appropriate time in the 445a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * overall transition for this scene change. A null value means no animation 446a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki * should be run. 447a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki */ 448a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, 449a6f2ebe33d03c42114b0082720cf9c42f7dad5a3Yuichi Araki TransitionValues endValues) { 4504e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki return null; 451733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki } 452733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki 453756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki @Override 454dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki public boolean isTransitionRequired(TransitionValues startValues, TransitionValues newValues) { 455dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki if (startValues == null && newValues == null) { 456756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki return false; 457756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki } 458dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki if (startValues != null && newValues != null 459dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki && newValues.values.containsKey(PROPNAME_VISIBILITY) 460dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki != startValues.values.containsKey(PROPNAME_VISIBILITY)) { 461dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki // The transition wasn't targeted in either the start or end, so it couldn't 462dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki // have changed. 463dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki return false; 464dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki } 465dfbc6c9b02b6eba0f537185aaa4e00b2f31f1a74Yuichi Araki VisibilityInfo changeInfo = getVisibilityChangeInfo(startValues, newValues); 466756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki return changeInfo.mVisibilityChange && (changeInfo.mStartVisibility == View.VISIBLE 467756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki || changeInfo.mEndVisibility == View.VISIBLE); 468756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki } 469756a17bb7580d5bdbb4826e81b074ca5fedba1f5Yuichi Araki 470928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private static class DisappearListener extends AnimatorListenerAdapter 471928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki implements TransitionListener, AnimatorUtilsApi14.AnimatorPauseListenerCompat { 472928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 473928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private final View mView; 474928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private final int mFinalVisibility; 475928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private final ViewGroup mParent; 476928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private final boolean mSuppressLayout; 477928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 478928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private boolean mLayoutSuppressed; 479928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki boolean mCanceled = false; 480928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 481928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki DisappearListener(View view, int finalVisibility, boolean suppressLayout) { 482928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mView = view; 483928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mFinalVisibility = finalVisibility; 484928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mParent = (ViewGroup) view.getParent(); 485928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mSuppressLayout = suppressLayout; 486928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Prevent a layout from including mView in its calculation. 487928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki suppressLayout(true); 488928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 489928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 490928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // This overrides both AnimatorListenerAdapter and 491928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // AnimatorUtilsApi14.AnimatorPauseListenerCompat 492928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 493928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationPause(Animator animation) { 494928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (!mCanceled) { 495928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ViewUtils.setTransitionVisibility(mView, mFinalVisibility); 496928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 497928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 498928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 499928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // This overrides both AnimatorListenerAdapter and 500928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // AnimatorUtilsApi14.AnimatorPauseListenerCompat 501928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 502928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationResume(Animator animation) { 503928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (!mCanceled) { 504928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ViewUtils.setTransitionVisibility(mView, View.VISIBLE); 505928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 506928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 507928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 508928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 509928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationCancel(Animator animation) { 510928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mCanceled = true; 511928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 512928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 513928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 514928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationRepeat(Animator animation) { 515928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 516928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 517928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 518928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationStart(Animator animation) { 519928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 520928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 521928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 522928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onAnimationEnd(Animator animation) { 523928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki hideViewWhenNotCanceled(); 524928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 525928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 526928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 527928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onTransitionStart(@NonNull Transition transition) { 528928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Do nothing 529928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 530928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 531928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 532928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onTransitionEnd(@NonNull Transition transition) { 533928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki hideViewWhenNotCanceled(); 534928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki transition.removeListener(this); 535928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 536928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 537928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 538928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onTransitionCancel(@NonNull Transition transition) { 539928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 540928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 541928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 542928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onTransitionPause(@NonNull Transition transition) { 543928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki suppressLayout(false); 544928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 545928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 546928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki @Override 547928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki public void onTransitionResume(@NonNull Transition transition) { 548928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki suppressLayout(true); 549928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 550928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 551928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private void hideViewWhenNotCanceled() { 552928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (!mCanceled) { 553928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Recreate the parent's display list in case it includes mView. 554928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ViewUtils.setTransitionVisibility(mView, mFinalVisibility); 555928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (mParent != null) { 556928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mParent.invalidate(); 557928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 558928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 559928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki // Layout is allowed now that the View is in its final state 560928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki suppressLayout(false); 561928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 562928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 563928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki private void suppressLayout(boolean suppress) { 564928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki if (mSuppressLayout && mLayoutSuppressed != suppress && mParent != null) { 565928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki mLayoutSuppressed = suppress; 566928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki ViewGroupUtils.suppressLayout(mParent, suppress); 567928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 568928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 569928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki } 570928ae3c90e1410c734136bb39d55517efc79714fYuichi Araki 571733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki // TODO: Implement API 23; isTransitionRequired 572733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki 573733b5aaadf1b1f5dc3038876dbfbabb79f649b03Yuichi Araki} 574