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