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; 20faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.AnimatorListenerAdapter; 21faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.AnimatorSet; 22faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.ObjectAnimator; 23faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.RectEvaluator; 24faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.animation.ValueAnimator; 25faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.graphics.Bitmap; 26faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.graphics.Canvas; 27faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.graphics.Rect; 28faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.graphics.drawable.BitmapDrawable; 29faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.Log; 30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.SurfaceView; 31faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.TextureView; 32faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.View; 33faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup; 344f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haaseimport android.view.ViewOverlay; 35faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 3608735185f8105710e18ad02297461bec9268e514Chet Haaseimport java.util.Map; 37faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 38faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/** 39faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * This transition captures bitmap representations of target views before and 40faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * after the scene change and fades between them. 41faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 42faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * <p>Note: This transition is not compatible with {@link TextureView} 43faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * or {@link SurfaceView}.</p> 44d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * 45d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @hide 46faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haasepublic class Crossfade extends Transition { 48faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // TODO: Add a hook that lets a Transition call user code to query whether it should run on 49faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // a given target view. This would save bitmap comparisons in this transition, for example. 50faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 51faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private static final String LOG_TAG = "Crossfade"; 52faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 53faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private static final String PROPNAME_BITMAP = "android:crossfade:bitmap"; 54faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private static final String PROPNAME_DRAWABLE = "android:crossfade:drawable"; 55faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private static final String PROPNAME_BOUNDS = "android:crossfade:bounds"; 56faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 57faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private static RectEvaluator sRectEvaluator = new RectEvaluator(); 58faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 594f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase private int mFadeBehavior = FADE_BEHAVIOR_REVEAL; 604f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase private int mResizeBehavior = RESIZE_BEHAVIOR_SCALE; 614f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 624f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase /** 634f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * Flag specifying that the fading animation should cross-fade 644f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * between the old and new representation of all affected target 654f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * views. This means that the old representation will fade out 664f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * while the new one fades in. This effect may work well on views 674f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * without solid backgrounds, such as TextViews. 684f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * 694f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * @see #setFadeBehavior(int) 704f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase */ 714f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase public static final int FADE_BEHAVIOR_CROSSFADE = 0; 724f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase /** 734f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * Flag specifying that the fading animation should reveal the 744f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * new representation of all affected target views. This means 754f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * that the old representation will fade out, gradually 764f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * revealing the new representation, which remains opaque 774f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * the whole time. This effect may work well on views 784f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * with solid backgrounds, such as ImageViews. 794f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * 804f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * @see #setFadeBehavior(int) 814f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase */ 824f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase public static final int FADE_BEHAVIOR_REVEAL = 1; 83c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase /** 84c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase * Flag specifying that the fading animation should first fade 85c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase * out the original representation completely and then fade in the 86c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase * new one. This effect may be more suitable than the other 87c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase * fade behaviors for views with. 88c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase * 89c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase * @see #setFadeBehavior(int) 90c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase */ 91c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase public static final int FADE_BEHAVIOR_OUT_IN = 2; 924f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 934f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase /** 944f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * Flag specifying that the transition should not animate any 954f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * changes in size between the old and new target views. 964f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * This means that no scaling will take place as a result of 974f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * this transition 984f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * 994f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * @see #setResizeBehavior(int) 1004f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase */ 1014f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase public static final int RESIZE_BEHAVIOR_NONE = 0; 1024f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase /** 1034f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * Flag specifying that the transition should animate any 1044f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * changes in size between the old and new target views. 1054f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * This means that the animation will scale the start/end 1064f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * representations of affected views from the starting size 1074f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * to the ending size over the course of the animation. 1084f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * This effect may work well on images, but is not recommended 1094f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * for text. 1104f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * 1114f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * @see #setResizeBehavior(int) 1124f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase */ 1134f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase public static final int RESIZE_BEHAVIOR_SCALE = 1; 1144f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 1154f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase // TODO: Add fade/resize behaviors to xml resources 1164f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 1174f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase /** 1184f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * Sets the type of fading animation that will be run, one of 1194f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * {@link #FADE_BEHAVIOR_CROSSFADE} and {@link #FADE_BEHAVIOR_REVEAL}. 1204f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * 1214f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * @param fadeBehavior The type of fading animation to use when this 1224f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * transition is run. 1234f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase */ 124d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public Crossfade setFadeBehavior(int fadeBehavior) { 125c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase if (fadeBehavior >= FADE_BEHAVIOR_CROSSFADE && fadeBehavior <= FADE_BEHAVIOR_OUT_IN) { 1264f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase mFadeBehavior = fadeBehavior; 1274f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 128d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase return this; 1294f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 1304f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 131d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase /** 132d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Returns the fading behavior of the animation. 133d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * 134d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @return This crossfade object. 135d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @see #setFadeBehavior(int) 136d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase */ 1374f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase public int getFadeBehavior() { 1384f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase return mFadeBehavior; 1394f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 1404f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 1414f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase /** 1424f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * Sets the type of resizing behavior that will be used during the 1434f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * transition animation, one of {@link #RESIZE_BEHAVIOR_NONE} and 1444f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * {@link #RESIZE_BEHAVIOR_SCALE}. 1454f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * 1464f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * @param resizeBehavior The type of resizing behavior to use when this 1474f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase * transition is run. 1484f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase */ 149d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public Crossfade setResizeBehavior(int resizeBehavior) { 1504f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase if (resizeBehavior >= RESIZE_BEHAVIOR_NONE && resizeBehavior <= RESIZE_BEHAVIOR_SCALE) { 1514f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase mResizeBehavior = resizeBehavior; 1524f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 153d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase return this; 1544f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 1554f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 156d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase /** 157d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Returns the resizing behavior of the animation. 158d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * 159d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @return This crossfade object. 160d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * @see #setResizeBehavior(int) 161d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase */ 1624f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase public int getResizeBehavior() { 1634f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase return mResizeBehavior; 1644f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 1654f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase 166faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase @Override 167d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, 168faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TransitionValues endValues) { 169faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (startValues == null || endValues == null) { 1702ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase return null; 171faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 172c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase final boolean useParentOverlay = mFadeBehavior != FADE_BEHAVIOR_REVEAL; 1734f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase final View view = endValues.view; 17408735185f8105710e18ad02297461bec9268e514Chet Haase Map<String, Object> startVals = startValues.values; 17508735185f8105710e18ad02297461bec9268e514Chet Haase Map<String, Object> endVals = endValues.values; 1762ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase Rect startBounds = (Rect) startVals.get(PROPNAME_BOUNDS); 1772ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase Rect endBounds = (Rect) endVals.get(PROPNAME_BOUNDS); 178faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Bitmap startBitmap = (Bitmap) startVals.get(PROPNAME_BITMAP); 179faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Bitmap endBitmap = (Bitmap) endVals.get(PROPNAME_BITMAP); 1802ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase final BitmapDrawable startDrawable = (BitmapDrawable) startVals.get(PROPNAME_DRAWABLE); 1812ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase final BitmapDrawable endDrawable = (BitmapDrawable) endVals.get(PROPNAME_DRAWABLE); 182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (Transition.DBG) { 183faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Log.d(LOG_TAG, "StartBitmap.sameAs(endBitmap) = " + startBitmap.sameAs(endBitmap) + 184faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase " for start, end: " + startBitmap + ", " + endBitmap); 185faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 186faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (startDrawable != null && endDrawable != null && !startBitmap.sameAs(endBitmap)) { 187c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase ViewOverlay overlay = useParentOverlay ? 188c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase ((ViewGroup) view.getParent()).getOverlay() : view.getOverlay(); 1894f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase if (mFadeBehavior == FADE_BEHAVIOR_REVEAL) { 1904f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase overlay.add(endDrawable); 1914f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 1924f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase overlay.add(startDrawable); 1932ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // The transition works by placing the end drawable under the start drawable and 1942ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // gradually fading out the start drawable. So it's not really a cross-fade, but rather 1952ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // a reveal of the end scene over time. Also, animate the bounds of both drawables 1962ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // to mimic the change in the size of the view itself between scenes. 197c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase ObjectAnimator anim; 198c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase if (mFadeBehavior == FADE_BEHAVIOR_OUT_IN) { 199c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase // Fade out completely halfway through the transition 200c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase anim = ObjectAnimator.ofInt(startDrawable, "alpha", 255, 0, 0); 201c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase } else { 202c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase anim = ObjectAnimator.ofInt(startDrawable, "alpha", 0); 203c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase } 2042ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 2052ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase @Override 2062ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase public void onAnimationUpdate(ValueAnimator animation) { 2072ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // TODO: some way to auto-invalidate views based on drawable changes? callbacks? 2082ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase view.invalidate(startDrawable.getBounds()); 2094f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 2102ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase }); 2112ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase ObjectAnimator anim1 = null; 212c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase if (mFadeBehavior == FADE_BEHAVIOR_OUT_IN) { 213c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase // start fading in halfway through the transition 214c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase anim1 = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 0, 1); 215c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase } else if (mFadeBehavior == FADE_BEHAVIOR_CROSSFADE) { 2162ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase anim1 = ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1); 217faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 218faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (Transition.DBG) { 2192ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase Log.d(LOG_TAG, "Crossfade: created anim " + anim + " for start, end values " + 2202ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase startValues + ", " + endValues); 2212ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase } 2222ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase anim.addListener(new AnimatorListenerAdapter() { 2232ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase @Override 2242ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase public void onAnimationEnd(Animator animation) { 225c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase ViewOverlay overlay = useParentOverlay ? 226c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase ((ViewGroup) view.getParent()).getOverlay() : view.getOverlay(); 2272ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase overlay.remove(startDrawable); 2282ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase if (mFadeBehavior == FADE_BEHAVIOR_REVEAL) { 2292ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase overlay.remove(endDrawable); 2302ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase } 2312ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase } 2322ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase }); 2332ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase AnimatorSet set = new AnimatorSet(); 2342ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase set.playTogether(anim); 2352ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase if (anim1 != null) { 2362ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase set.playTogether(anim1); 237faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 2382ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE && !startBounds.equals(endBounds)) { 2392ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase if (Transition.DBG) { 2402ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase Log.d(LOG_TAG, "animating from startBounds to endBounds: " + 2412ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase startBounds + ", " + endBounds); 2422ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase } 2432ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase Animator anim2 = ObjectAnimator.ofObject(startDrawable, "bounds", 2444f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase sRectEvaluator, startBounds, endBounds); 2452ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase set.playTogether(anim2); 2462ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase if (mResizeBehavior == RESIZE_BEHAVIOR_SCALE) { 2472ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // TODO: How to handle resizing with a CROSSFADE (vs. REVEAL) effect 2482ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase // when we are animating the view directly? 2492ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase Animator anim3 = ObjectAnimator.ofObject(endDrawable, "bounds", 2502ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase sRectEvaluator, startBounds, endBounds); 2512ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase set.playTogether(anim3); 2522ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase } 2534f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 2542ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase return set; 2552ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase } else { 2562ea7f8b9c5f903050d42c1af57406bf528979f45Chet Haase return null; 257faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 258faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 259faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 260d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase private void captureValues(TransitionValues transitionValues) { 261d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase View view = transitionValues.view; 2624f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight()); 263c81a8493884c7f432d6bd5b98aca3fbdc93b355bChet Haase if (mFadeBehavior != FADE_BEHAVIOR_REVEAL) { 2644f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase bounds.offset(view.getLeft(), view.getTop()); 2654f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase } 266d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transitionValues.values.put(PROPNAME_BOUNDS, bounds); 267faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 268faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (Transition.DBG) { 269d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase Log.d(LOG_TAG, "Captured bounds " + transitionValues.values.get(PROPNAME_BOUNDS)); 270faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 271faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), 272faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Bitmap.Config.ARGB_8888); 273faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (view instanceof TextureView) { 274faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase bitmap = ((TextureView) view).getBitmap(); 275faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 276faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Canvas c = new Canvas(bitmap); 277faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase view.draw(c); 278faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 279d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transitionValues.values.put(PROPNAME_BITMAP, bitmap); 280faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // TODO: I don't have resources, can't call the non-deprecated method? 281faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase BitmapDrawable drawable = new BitmapDrawable(bitmap); 282faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // TODO: lrtb will be wrong if the view has transXY set 2834f0c4672ac7fd6b8135e27d8f816da2ebaf7d63aChet Haase drawable.setBounds(bounds); 284d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transitionValues.values.put(PROPNAME_DRAWABLE, drawable); 285faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 286faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 287d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase @Override 288d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public void captureStartValues(TransitionValues transitionValues) { 289d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase captureValues(transitionValues); 290d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } 291d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase 292d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase @Override 293d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase public void captureEndValues(TransitionValues transitionValues) { 294d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase captureValues(transitionValues); 295d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } 296faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase} 297