1faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/* 2faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Copyright (C) 2013 The Android Open Source Project 3faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 4faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * you may not use this file except in compliance with the License. 6faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * You may obtain a copy of the License at 7faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 8faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * http://www.apache.org/licenses/LICENSE-2.0 9faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 10faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Unless required by applicable law or agreed to in writing, software 11faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * See the License for the specific language governing permissions and 14faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * limitations under the License. 15faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 166ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase 17d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haasepackage android.transition; 18faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 19faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.Animator; 20fcfe531e742bd1731664080cb2ed3e66189d7f17George Mountimport android.animation.Animator.AnimatorListener; 21fcfe531e742bd1731664080cb2ed3e66189d7f17George Mountimport android.animation.Animator.AnimatorPauseListener; 227764b920f21e0b9250122ff26533d5dac98df6b3George Mountimport android.annotation.IntDef; 23ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.content.Context; 24ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.content.res.TypedArray; 25ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.util.AttributeSet; 26faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.View; 27faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup; 28fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 297764b920f21e0b9250122ff26533d5dac98df6b3George Mountimport com.android.internal.R; 307764b920f21e0b9250122ff26533d5dac98df6b3George Mount 317764b920f21e0b9250122ff26533d5dac98df6b3George Mountimport java.lang.annotation.Retention; 327764b920f21e0b9250122ff26533d5dac98df6b3George Mountimport java.lang.annotation.RetentionPolicy; 337764b920f21e0b9250122ff26533d5dac98df6b3George Mount 34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/** 35faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * This transition tracks changes to the visibility of target views in the 36faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * start and end scenes. Visibility is determined not just by the 37faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * {@link View#setVisibility(int)} state of views, but also whether 38faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * views exist in the current view hierarchy. The class is intended to be a 39faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * utility for subclasses such as {@link Fade}, which use this visibility 40faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * information to determine the specific animations to run when visibility 4135a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase * changes occur. Subclasses should implement one or both of the methods 42d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}, 43d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or 44d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}, 45d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}. 46faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haasepublic abstract class Visibility extends Transition { 48faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 496ceac2eafbb43dafd18bf547fee6fe51aee6b59bGeorge Mount static final String PROPNAME_VISIBILITY = "android:visibility:visibility"; 50faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private static final String PROPNAME_PARENT = "android:visibility:parent"; 51d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation"; 52d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount 537764b920f21e0b9250122ff26533d5dac98df6b3George Mount /** @hide */ 547764b920f21e0b9250122ff26533d5dac98df6b3George Mount @Retention(RetentionPolicy.SOURCE) 557764b920f21e0b9250122ff26533d5dac98df6b3George Mount @IntDef(flag=true, value={MODE_IN, MODE_OUT}) 567764b920f21e0b9250122ff26533d5dac98df6b3George Mount @interface VisibilityMode {} 577764b920f21e0b9250122ff26533d5dac98df6b3George Mount 5818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount /** 5918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * Mode used in {@link #setMode(int)} to make the transition 6018ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * operate on targets that are appearing. Maybe be combined with 61ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount * {@link #MODE_OUT} to target Visibility changes both in and out. 6218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount */ 63ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount public static final int MODE_IN = 0x1; 6418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount 6518ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount /** 6618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * Mode used in {@link #setMode(int)} to make the transition 6718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * operate on targets that are disappearing. Maybe be combined with 68ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount * {@link #MODE_IN} to target Visibility changes both in and out. 6918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount */ 70ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount public static final int MODE_OUT = 0x2; 7118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount 72af78bdd615ecd5ce9d41a6160ce9f53fa269b119Chet Haase private static final String[] sTransitionProperties = { 73199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase PROPNAME_VISIBILITY, 7420559079ab05aa5e976bb0f7aa63fd9e6868f02eGeorge Mount PROPNAME_PARENT, 75199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase }; 76faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 776ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase private static class VisibilityInfo { 786ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase boolean visibilityChange; 796ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase boolean fadeIn; 806ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase int startVisibility; 816ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase int endVisibility; 8235a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase ViewGroup startParent; 8335a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase ViewGroup endParent; 846ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase } 856ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase 86ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount private int mMode = MODE_IN | MODE_OUT; 871349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount private boolean mSuppressLayout = true; 8818ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount 89ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount public Visibility() {} 90ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 91ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount public Visibility(Context context, AttributeSet attrs) { 92ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount super(context, attrs); 93ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition); 943b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0); 95ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount a.recycle(); 96ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (mode != 0) { 97ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount setMode(mode); 98ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 99ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 100ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 10118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount /** 1021349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount * This tells the Visibility transition to suppress layout during the transition and release 1031349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount * the suppression after the transition. 1041349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount * @hide 1051349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount */ 1061349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount public void setSuppressLayout(boolean suppress) { 1071349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount this.mSuppressLayout = suppress; 1081349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount } 1091349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount 1101349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount /** 11118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * Changes the transition to support appearing and/or disappearing Views, depending 11218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * on <code>mode</code>. 11318ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * 11418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount * @param mode The behavior supported by this transition, a combination of 115ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount * {@link #MODE_IN} and {@link #MODE_OUT}. 1163b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode 11718ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount */ 1187764b920f21e0b9250122ff26533d5dac98df6b3George Mount public void setMode(@VisibilityMode int mode) { 119ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount if ((mode & ~(MODE_IN | MODE_OUT)) != 0) { 120ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount throw new IllegalArgumentException("Only MODE_IN and MODE_OUT flags are allowed"); 12118ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount } 12218ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount mMode = mode; 12318ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount } 12418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount 125ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount /** 126ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount * Returns whether appearing and/or disappearing Views are supported. 127ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount * 128ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount * Returns whether appearing and/or disappearing Views are supported. A combination of 129ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount * {@link #MODE_IN} and {@link #MODE_OUT}. 1303b2cd1d59fd894ac67a044c6c540fa69360a34a2Craig Mautner * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode 131ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount */ 1327764b920f21e0b9250122ff26533d5dac98df6b3George Mount @VisibilityMode 133ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount public int getMode() { 134ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount return mMode; 135ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 136ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 137faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase @Override 138199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase public String[] getTransitionProperties() { 139199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase return sTransitionProperties; 140199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase } 141199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase 142629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount private void captureValues(TransitionValues transitionValues) { 143629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount int visibility = transitionValues.view.getVisibility(); 144d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transitionValues.values.put(PROPNAME_VISIBILITY, visibility); 145d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent()); 146d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount int[] loc = new int[2]; 147d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount transitionValues.view.getLocationOnScreen(loc); 148d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc); 149d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } 150d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase 151d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase @Override 152d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public void captureStartValues(TransitionValues transitionValues) { 153629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount captureValues(transitionValues); 154d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } 155d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase 156199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase @Override 157d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public void captureEndValues(TransitionValues transitionValues) { 158629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount captureValues(transitionValues); 159faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 160faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 161199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase /** 162199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * Returns whether the view is 'visible' according to the given values 163199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * object. This is determined by testing the same properties in the values 164199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * object that are used to determine whether the object is appearing or 165199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * disappearing in the {@link 166d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)} 167199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * method. This method can be called by, for example, subclasses that want 168199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * to know whether the object is visible in the same way that Visibility 169199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * determines it for the actual animation. 170199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * 171199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * @param values The TransitionValues object that holds the information by 172199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * which visibility is determined. 173199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * @return True if the view reference by <code>values</code> is visible, 174199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase * false otherwise. 175199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase */ 176199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase public boolean isVisible(TransitionValues values) { 177199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase if (values == null) { 178199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase return false; 179199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase } 180199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY); 181199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase View parent = (View) values.values.get(PROPNAME_PARENT); 182199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase 183199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase return visibility == View.VISIBLE && parent != null; 184199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase } 185199acdfcc98e852975dd7edfbcb822ba5e73146fChet Haase 1860653f2596f769956f6c1bf491505979ec40453e3Todd Volkert private static VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues, 187faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TransitionValues endValues) { 1887660d121b2ef21164ed33e6091e5dd50f5d0f939Chet Haase final VisibilityInfo visInfo = new VisibilityInfo(); 1896ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = false; 1906ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = false; 19131a217290cf376d0573fc36e21c8940987485019George Mount if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) { 1926ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY); 19335a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT); 194faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 1956ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.startVisibility = -1; 1966ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.startParent = null; 197faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 19831a217290cf376d0573fc36e21c8940987485019George Mount if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) { 1996ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY); 20035a457a3bac0851a1fabd6cda58d1ea67f997b33Chet Haase visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT); 201faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 2026ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.endVisibility = -1; 2036ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.endParent = null; 204faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 205faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (startValues != null && endValues != null) { 2066ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase if (visInfo.startVisibility == visInfo.endVisibility && 2076ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.startParent == visInfo.endParent) { 2086ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase return visInfo; 209faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 2106ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase if (visInfo.startVisibility != visInfo.endVisibility) { 2116ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase if (visInfo.startVisibility == View.VISIBLE) { 2126ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = false; 2136ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = true; 2146ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase } else if (visInfo.endVisibility == View.VISIBLE) { 2156ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = true; 2166ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = true; 217faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 218faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // no visibilityChange if going between INVISIBLE and GONE 2196ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase } else if (visInfo.startParent != visInfo.endParent) { 2206ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase if (visInfo.endParent == null) { 2216ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = false; 2226ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = true; 2236ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase } else if (visInfo.startParent == null) { 2246ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = true; 2256ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = true; 226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 227faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 228faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 22979b2781aa763cbd770f690c16af4448139f37061George Mount } else if (startValues == null && visInfo.endVisibility == View.VISIBLE) { 2306ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = true; 2316ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = true; 23279b2781aa763cbd770f690c16af4448139f37061George Mount } else if (endValues == null && visInfo.startVisibility == View.VISIBLE) { 2336ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.fadeIn = false; 2346ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase visInfo.visibilityChange = true; 235faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 2366ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase return visInfo; 237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 238faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase @Override 240d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, 241faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TransitionValues endValues) { 2426ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues); 24330da61d477bcb6cc7718f9516c444359352fe148George Mount if (visInfo.visibilityChange 24430da61d477bcb6cc7718f9516c444359352fe148George Mount && (visInfo.startParent != null || visInfo.endParent != null)) { 24530da61d477bcb6cc7718f9516c444359352fe148George Mount if (visInfo.fadeIn) { 24630da61d477bcb6cc7718f9516c444359352fe148George Mount return onAppear(sceneRoot, startValues, visInfo.startVisibility, 24730da61d477bcb6cc7718f9516c444359352fe148George Mount endValues, visInfo.endVisibility); 24830da61d477bcb6cc7718f9516c444359352fe148George Mount } else { 24930da61d477bcb6cc7718f9516c444359352fe148George Mount return onDisappear(sceneRoot, startValues, visInfo.startVisibility, 25030da61d477bcb6cc7718f9516c444359352fe148George Mount endValues, visInfo.endVisibility 25130da61d477bcb6cc7718f9516c444359352fe148George Mount ); 252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 253faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 254faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return null; 255faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 256faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 257faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 258d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * The default implementation of this method calls 259d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}. 260d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * Subclasses should override this method or 261d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}. 262d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * if they need to create an Animator when targets appear. 263d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * The method should only be called by the Visibility class; it is 264d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * not intended to be called from external classes. 265faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 266d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param sceneRoot The root of the transition hierarchy 267d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param startValues The target values in the start scene 268d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param startVisibility The target visibility in the start scene 269d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param endValues The target values in the end scene 270d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param endVisibility The target visibility in the end scene 271d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @return An Animator to be started at the appropriate time in the 272d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * overall transition for this scene change. A null value means no animation 273d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * should be run. 274faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 275d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public Animator onAppear(ViewGroup sceneRoot, 2766ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase TransitionValues startValues, int startVisibility, 2776ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase TransitionValues endValues, int endVisibility) { 278ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount if ((mMode & MODE_IN) != MODE_IN || endValues == null) { 27918ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount return null; 28018ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount } 281e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout if (startValues == null) { 282e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout VisibilityInfo parentVisibilityInfo = null; 283e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout View endParent = (View) endValues.view.getParent(); 284e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout TransitionValues startParentValues = getMatchedTransitionValues(endParent, 285e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout false); 286e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout TransitionValues endParentValues = getTransitionValues(endParent, false); 287e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout parentVisibilityInfo = 288e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout getVisibilityChangeInfo(startParentValues, endParentValues); 289e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout if (parentVisibilityInfo.visibilityChange) { 290e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout return null; 291e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout } 292e988ee1eb2cc0cd345e42bcc549363a0e8c339aaCraig Stout } 293d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount return onAppear(sceneRoot, endValues.view, startValues, endValues); 294d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 295d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount 296d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount /** 297d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * The default implementation of this method returns a null Animator. Subclasses should 298d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * override this method to make targets appear with the desired transition. The 299d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * method should only be called from 300d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}. 301d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * 302d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param sceneRoot The root of the transition hierarchy 303d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param view The View to make appear. This will be in the target scene's View hierarchy and 304d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * will be VISIBLE. 305d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param startValues The target values in the start scene 306d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param endValues The target values in the end scene 307d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @return An Animator to be started at the appropriate time in the 308d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * overall transition for this scene change. A null value means no animation 309d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * should be run. 310d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount */ 311d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, 312d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount TransitionValues endValues) { 3132ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase return null; 314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 315faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 316faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 317d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * Subclasses should override this method or 318d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)} 319d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * if they need to create an Animator when targets disappear. 320d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * The method should only be called by the Visibility class; it is 321d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * not intended to be called from external classes. 322d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * <p> 323d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * The default implementation of this method attempts to find a View to use to call 324d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}, 325d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * based on the situation of the View in the View hierarchy. For example, 326d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * if a View was simply removed from its parent, then the View will be added 327d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * into a {@link android.view.ViewGroupOverlay} and passed as the <code>view</code> 328d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}. 329d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE}, 330d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * then it can be used as the <code>view</code> and the visibility will be changed 331d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * to {@link View#VISIBLE} for the duration of the animation. However, if a View 332d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * is in a hierarchy which is also altering its visibility, the situation can be 333d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * more complicated. In general, if a view that is no longer in the hierarchy in 334d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * the end scene still has a parent (so its parent hierarchy was removed, but it 335d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * was not removed from its parent), then it will be left alone to avoid side-effects from 336d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * improperly removing it from its parent. The only exception to this is if 337d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int, 338d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * android.content.Context) created from a layout resource file}, then it is considered 339d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * safe to un-parent the starting scene view in order to make it disappear.</p> 3406ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase * 341d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param sceneRoot The root of the transition hierarchy 342d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param startValues The target values in the start scene 343d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param startVisibility The target visibility in the start scene 344d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param endValues The target values in the end scene 345d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @param endVisibility The target visibility in the end scene 346d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @return An Animator to be started at the appropriate time in the 347d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * overall transition for this scene change. A null value means no animation 348d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * should be run. 349faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 350d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public Animator onDisappear(ViewGroup sceneRoot, 3516ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase TransitionValues startValues, int startVisibility, 3526ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase TransitionValues endValues, int endVisibility) { 353ad88e1b1b2c57fa56bde68764b22240d145fa0efGeorge Mount if ((mMode & MODE_OUT) != MODE_OUT) { 35418ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount return null; 35518ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount } 35618ab79967ce8bcde4b1507164ac8186e5135622eGeorge Mount 357d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount View startView = (startValues != null) ? startValues.view : null; 358d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount View endView = (endValues != null) ? endValues.view : null; 359d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount View overlayView = null; 360d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount View viewToKeep = null; 361d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (endView == null || endView.getParent() == null) { 362d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (endView != null) { 363d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // endView was removed from its parent - add it to the overlay 364d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount overlayView = endView; 365d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } else if (startView != null) { 366d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // endView does not exist. Use startView only under certain 367d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // conditions, because placing a view in an overlay necessitates 368d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // it being removed from its current parent 369d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (startView.getParent() == null) { 370d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // no parent - safe to use 371d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount overlayView = startView; 372d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount } else if (startView.getParent() instanceof View) { 373d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount View startParent = (View) startView.getParent(); 37479b2781aa763cbd770f690c16af4448139f37061George Mount TransitionValues startParentValues = getTransitionValues(startParent, true); 3759f1ac3976ea3aa08c20c06fa6678e367e1ed424dGeorge Mount TransitionValues endParentValues = getMatchedTransitionValues(startParent, 3769f1ac3976ea3aa08c20c06fa6678e367e1ed424dGeorge Mount true); 37779b2781aa763cbd770f690c16af4448139f37061George Mount VisibilityInfo parentVisibilityInfo = 37879b2781aa763cbd770f690c16af4448139f37061George Mount getVisibilityChangeInfo(startParentValues, endParentValues); 37979b2781aa763cbd770f690c16af4448139f37061George Mount if (!parentVisibilityInfo.visibilityChange) { 38079b2781aa763cbd770f690c16af4448139f37061George Mount overlayView = TransitionUtils.copyViewImage(sceneRoot, startView, 38179b2781aa763cbd770f690c16af4448139f37061George Mount startParent); 382d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount } else if (startParent.getParent() == null) { 383d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount int id = startParent.getId(); 384d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount if (id != View.NO_ID && sceneRoot.findViewById(id) != null 385d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount && mCanRemoveViews) { 386d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // no parent, but its parent is unparented but the parent 387d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // hierarchy has been replaced by a new hierarchy with the same id 388d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount // and it is safe to un-parent startView 389d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount overlayView = startView; 390d4c3c91dd0757eec9703ef90ea4c5a7ee99f18caGeorge Mount } 391d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 392d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 393d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 394d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } else { 395d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // visibility change 396d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (endVisibility == View.INVISIBLE) { 397d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount viewToKeep = endView; 398d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } else { 399d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // Becoming GONE 400d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (startView == endView) { 401d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount viewToKeep = endView; 402d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } else { 403d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount overlayView = startView; 404d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 405d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 406d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 407d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount final int finalVisibility = endVisibility; 408d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount final ViewGroup finalSceneRoot = sceneRoot; 409d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount 410d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (overlayView != null) { 411d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount // TODO: Need to do this for general case of adding to overlay 412d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION); 413d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount int screenX = screenLoc[0]; 414d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount int screenY = screenLoc[1]; 415d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount int[] loc = new int[2]; 416d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount sceneRoot.getLocationOnScreen(loc); 417d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft()); 418d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop()); 419d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount sceneRoot.getOverlay().add(overlayView); 420d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues); 421d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (animator == null) { 422d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount sceneRoot.getOverlay().remove(overlayView); 423d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } else { 424d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount final View finalOverlayView = overlayView; 425fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount addListener(new TransitionListenerAdapter() { 426d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount @Override 427fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onTransitionEnd(Transition transition) { 428d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount finalSceneRoot.getOverlay().remove(finalOverlayView); 42925f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount transition.removeListener(this); 430d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 431d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount }); 432d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 433d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount return animator; 434d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 435d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount 436d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount if (viewToKeep != null) { 437629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount int originalVisibility = viewToKeep.getVisibility(); 438629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount viewToKeep.setTransitionVisibility(View.VISIBLE); 439d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues); 440b5ef7f8c6d4629b2998de6c0b27bc1a4779b3e49George Mount if (animator != null) { 441fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount DisappearListener disappearListener = new DisappearListener(viewToKeep, 4421349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount finalVisibility, mSuppressLayout); 443fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount animator.addListener(disappearListener); 4440b056a0ac3147b4a856b342b8fe25c745cf21058George Mount animator.addPauseListener(disappearListener); 445fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount addListener(disappearListener); 446629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount } else { 447e5a93aa81ce79bf7fa529b09b50d7473f07a74a2George Mount viewToKeep.setTransitionVisibility(originalVisibility); 448d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 449d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount return animator; 450d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 451d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount return null; 452d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } 453d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount 4544c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount @Override 455aef1ae33915471983f10342dfbf6e37cb6f8c7a5George Mount public boolean isTransitionRequired(TransitionValues startValues, TransitionValues newValues) { 456aef1ae33915471983f10342dfbf6e37cb6f8c7a5George Mount if (startValues == null && newValues == null) { 4574c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount return false; 4584c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount } 459aef1ae33915471983f10342dfbf6e37cb6f8c7a5George Mount if (startValues != null && newValues != null && 460cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount newValues.values.containsKey(PROPNAME_VISIBILITY) != 461aef1ae33915471983f10342dfbf6e37cb6f8c7a5George Mount startValues.values.containsKey(PROPNAME_VISIBILITY)) { 462cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount // The transition wasn't targeted in either the start or end, so it couldn't 463cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount // have changed. 464cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount return false; 465cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount } 466aef1ae33915471983f10342dfbf6e37cb6f8c7a5George Mount VisibilityInfo changeInfo = getVisibilityChangeInfo(startValues, newValues); 4674c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE || 468cba01b2310e78fc2114ceed285f4e134469ae62bGeorge Mount changeInfo.endVisibility == View.VISIBLE); 4694c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount } 4704c20ea29728a80b42487b3ba1600d11d5ea47bccGeorge Mount 471d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount /** 472d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * The default implementation of this method returns a null Animator. Subclasses should 473d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * override this method to make targets disappear with the desired transition. The 474d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * method should only be called from 475d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}. 476d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * 477d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param sceneRoot The root of the transition hierarchy 478d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param view The View to make disappear. This will be in the target scene's View 479d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * hierarchy or in an {@link android.view.ViewGroupOverlay} and will be 480d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * VISIBLE. 481d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param startValues The target values in the start scene 482d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @param endValues The target values in the end scene 483d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * @return An Animator to be started at the appropriate time in the 484d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * overall transition for this scene change. A null value means no animation 485d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount * should be run. 486d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount */ 487d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, 488d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount TransitionValues endValues) { 4896ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase return null; 4906ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase } 491fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 492fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount private static class DisappearListener 493fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount extends TransitionListenerAdapter implements AnimatorListener, AnimatorPauseListener { 494fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount private final View mView; 495fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount private final int mFinalVisibility; 49621290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount private final ViewGroup mParent; 4971349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount private final boolean mSuppressLayout; 498fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 499a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount private boolean mLayoutSuppressed; 500fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount boolean mCanceled = false; 501fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 5021349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount public DisappearListener(View view, int finalVisibility, boolean suppressLayout) { 503fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount this.mView = view; 504fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount this.mFinalVisibility = finalVisibility; 50521290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount this.mParent = (ViewGroup) view.getParent(); 5061349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount this.mSuppressLayout = suppressLayout; 507a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount // Prevent a layout from including mView in its calculation. 508a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount suppressLayout(true); 509fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 510fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 511fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 512fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onAnimationPause(Animator animation) { 513629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount if (!mCanceled) { 514e5a93aa81ce79bf7fa529b09b50d7473f07a74a2George Mount mView.setTransitionVisibility(mFinalVisibility); 515fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 516fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 517fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 518fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 519fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onAnimationResume(Animator animation) { 520629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount if (!mCanceled) { 521e5a93aa81ce79bf7fa529b09b50d7473f07a74a2George Mount mView.setTransitionVisibility(View.VISIBLE); 522fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 523fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 524fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 525fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 526fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onAnimationCancel(Animator animation) { 527fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount mCanceled = true; 528fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 529fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 530fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 531fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onAnimationRepeat(Animator animation) { 532fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 533fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 534fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 535fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onAnimationStart(Animator animation) { 536fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 537fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 538fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 539fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onAnimationEnd(Animator animation) { 540fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount hideViewWhenNotCanceled(); 541fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 542fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 543fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount @Override 544fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount public void onTransitionEnd(Transition transition) { 545fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount hideViewWhenNotCanceled(); 54625f98a4c0156ec40d1d92cfe5a24459d9ffa6f91George Mount transition.removeListener(this); 547fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 548fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount 54921290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount @Override 55021290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount public void onTransitionPause(Transition transition) { 551a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount suppressLayout(false); 55221290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount } 55321290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount 55421290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount @Override 55521290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount public void onTransitionResume(Transition transition) { 556a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount suppressLayout(true); 55721290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount } 55821290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount 559fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount private void hideViewWhenNotCanceled() { 560a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount if (!mCanceled) { 561629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount // Recreate the parent's display list in case it includes mView. 562629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount mView.setTransitionVisibility(mFinalVisibility); 563629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount if (mParent != null) { 564629767288a7f551d651f0405fdd9ed04e807d56bGeorge Mount mParent.invalidate(); 56521290a62a58581eecd29f4895bb7319a0cb5721aGeorge Mount } 566a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount } 567a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount // Layout is allowed now that the View is in its final state 568a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount suppressLayout(false); 569a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount } 570a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount 571a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount private void suppressLayout(boolean suppress) { 5721349bb9c336e33bdb8a7edd3fdec9a7ecf8015d0George Mount if (mSuppressLayout && mLayoutSuppressed != suppress && mParent != null) { 573a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount mLayoutSuppressed = suppress; 574a7478ab9a7d36fbd8a0adaada613dff2a9fe77b4George Mount mParent.suppressLayout(suppress); 575fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 576fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 577fcfe531e742bd1731664080cb2ed3e66189d7f17George Mount } 578faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase} 579