12ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka/* 22ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * Copyright (C) 2012 The Android Open Source Project 32ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * 42ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 52ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * you may not use this file except in compliance with the License. 62ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * You may obtain a copy of the License at 72ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * 82ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * http://www.apache.org/licenses/LICENSE-2.0 92ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * 102ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * Unless required by applicable law or agreed to in writing, software 112ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 122ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * See the License for the specific language governing permissions and 142ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka * limitations under the License. 152ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka */ 162ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 182ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 192ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkaimport android.animation.Animator; 202ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkaimport android.animation.AnimatorSet; 212ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkaimport android.animation.ObjectAnimator; 222ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkaimport android.animation.PropertyValuesHolder; 232ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkaimport android.animation.ValueAnimator; 24e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Songimport android.annotation.TargetApi; 25e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Songimport android.os.Build; 26f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurkaimport android.view.View; 2763f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohenimport android.view.ViewAnimationUtils; 28f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurkaimport android.view.ViewTreeObserver; 292ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 30e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Songimport com.android.launcher3.util.UiThreadCircularReveal; 31e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Song 322ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkaimport java.util.HashSet; 337c70d64d4c814e3d48b69aa4d9daf0717d71bff5Michael Jurkaimport java.util.WeakHashMap; 342ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 352ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurkapublic class LauncherAnimUtils { 367c70d64d4c814e3d48b69aa4d9daf0717d71bff5Michael Jurka static WeakHashMap<Animator, Object> sAnimators = new WeakHashMap<Animator, Object>(); 37def8e655543384a2837b769d0bc43cdc252cbc53Michael Jurka static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() { 382ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public void onAnimationStart(Animator animation) { 397c70d64d4c814e3d48b69aa4d9daf0717d71bff5Michael Jurka sAnimators.put(animation, null); 402ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 412ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 422ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public void onAnimationRepeat(Animator animation) { 432ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 442ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 452ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public void onAnimationEnd(Animator animation) { 462ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka sAnimators.remove(animation); 472ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 482ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 492ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public void onAnimationCancel(Animator animation) { 502ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka sAnimators.remove(animation); 512ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 522ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka }; 532ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 542ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public static void cancelOnDestroyActivity(Animator a) { 55def8e655543384a2837b769d0bc43cdc252cbc53Michael Jurka a.addListener(sEndAnimListener); 562ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 572ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 58f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka // Helper method. Assumes a draw is pending, and that if the animation's duration is 0 59f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka // it should be cancelled 60f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public static void startAnimationAfterNextDraw(final Animator animator, final View view) { 61df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { 62df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka private boolean mStarted = false; 63f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public void onDraw() { 64df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka if (mStarted) return; 65df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka mStarted = true; 66f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka // Use this as a signal that the animation was cancelled 67f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka if (animator.getDuration() == 0) { 68f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka return; 69f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka } 70f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka animator.start(); 71df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka 72df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka final ViewTreeObserver.OnDrawListener listener = this; 73df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka view.post(new Runnable() { 74df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka public void run() { 75df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka view.getViewTreeObserver().removeOnDrawListener(listener); 76df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka } 77df96add095c82f9083f75305d8fa155c8192a4e6Michael Jurka }); 78f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka } 79f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka }); 80f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka } 81f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka 822ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public static void onDestroyActivity() { 837c70d64d4c814e3d48b69aa4d9daf0717d71bff5Michael Jurka HashSet<Animator> animators = new HashSet<Animator>(sAnimators.keySet()); 8415ba53a54c8b319e3ccdffa586fab1cfcd8971e5Winson Chung for (Animator a : animators) { 852ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka if (a.isRunning()) { 862ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka a.cancel(); 872ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 887c70d64d4c814e3d48b69aa4d9daf0717d71bff5Michael Jurka sAnimators.remove(a); 892ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 902ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 912ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 922ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka public static AnimatorSet createAnimatorSet() { 932ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka AnimatorSet anim = new AnimatorSet(); 942ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka cancelOnDestroyActivity(anim); 952ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka return anim; 962ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 972ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 98f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public static ValueAnimator ofFloat(View target, float... values) { 992ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka ValueAnimator anim = new ValueAnimator(); 1002ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka anim.setFloatValues(values); 1012ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka cancelOnDestroyActivity(anim); 1022ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka return anim; 1032ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 1042ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 105f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public static ObjectAnimator ofFloat(View target, String propertyName, float... values) { 1062ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka ObjectAnimator anim = new ObjectAnimator(); 1072ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka anim.setTarget(target); 1082ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka anim.setPropertyName(propertyName); 1092ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka anim.setFloatValues(values); 1102ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka cancelOnDestroyActivity(anim); 111f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka new FirstFrameAnimatorHelper(anim, target); 1122ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka return anim; 1132ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 1142ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka 115f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public static ObjectAnimator ofPropertyValuesHolder(View target, 1162ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka PropertyValuesHolder... values) { 1172ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka ObjectAnimator anim = new ObjectAnimator(); 1182ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka anim.setTarget(target); 1192ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka anim.setValues(values); 1202ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka cancelOnDestroyActivity(anim); 121f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka new FirstFrameAnimatorHelper(anim, target); 122f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka return anim; 123f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka } 124f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka 125f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka public static ObjectAnimator ofPropertyValuesHolder(Object target, 126f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka View view, PropertyValuesHolder... values) { 127f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka ObjectAnimator anim = new ObjectAnimator(); 128f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka anim.setTarget(target); 129f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka anim.setValues(values); 130f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka cancelOnDestroyActivity(anim); 131f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka new FirstFrameAnimatorHelper(anim, view); 1322ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka return anim; 1332ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka } 13463f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen 135e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Song @TargetApi(Build.VERSION_CODES.LOLLIPOP) 136e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Song public static ValueAnimator createCircularReveal(View view, int centerX, 13763f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen int centerY, float startRadius, float endRadius) { 138e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Song ValueAnimator anim = UiThreadCircularReveal.createCircularReveal(view, centerX, 13963f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen centerY, startRadius, endRadius); 140e612775922ec9f8cc4e5cb976bc62b3312a3de0eHyunyoung Song new FirstFrameAnimatorHelper(anim, view); 14163f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen return anim; 14263f1ec00fbbd109130d1e476371dbc9a87bb544dAdam Cohen } 1432ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka} 144