/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher3; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.os.Build; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewTreeObserver; import com.android.launcher3.util.UiThreadCircularReveal; import java.util.HashSet; import java.util.WeakHashMap; public class LauncherAnimUtils { static WeakHashMap sAnimators = new WeakHashMap(); static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() { public void onAnimationStart(Animator animation) { sAnimators.put(animation, null); } public void onAnimationRepeat(Animator animation) { } public void onAnimationEnd(Animator animation) { sAnimators.remove(animation); } public void onAnimationCancel(Animator animation) { sAnimators.remove(animation); } }; public static void cancelOnDestroyActivity(Animator a) { a.addListener(sEndAnimListener); } // Helper method. Assumes a draw is pending, and that if the animation's duration is 0 // it should be cancelled public static void startAnimationAfterNextDraw(final Animator animator, final View view) { view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { private boolean mStarted = false; public void onDraw() { if (mStarted) return; mStarted = true; // Use this as a signal that the animation was cancelled if (animator.getDuration() == 0) { return; } animator.start(); final ViewTreeObserver.OnDrawListener listener = this; view.post(new Runnable() { public void run() { view.getViewTreeObserver().removeOnDrawListener(listener); } }); } }); } public static void onDestroyActivity() { HashSet animators = new HashSet(sAnimators.keySet()); for (Animator a : animators) { if (a.isRunning()) { a.cancel(); } sAnimators.remove(a); } } public static AnimatorSet createAnimatorSet() { AnimatorSet anim = new AnimatorSet(); cancelOnDestroyActivity(anim); return anim; } public static ValueAnimator ofFloat(View target, float... values) { ValueAnimator anim = new ValueAnimator(); anim.setFloatValues(values); cancelOnDestroyActivity(anim); return anim; } public static ObjectAnimator ofFloat(View target, String propertyName, float... values) { ObjectAnimator anim = new ObjectAnimator(); anim.setTarget(target); anim.setPropertyName(propertyName); anim.setFloatValues(values); cancelOnDestroyActivity(anim); new FirstFrameAnimatorHelper(anim, target); return anim; } public static ObjectAnimator ofPropertyValuesHolder(View target, PropertyValuesHolder... values) { ObjectAnimator anim = new ObjectAnimator(); anim.setTarget(target); anim.setValues(values); cancelOnDestroyActivity(anim); new FirstFrameAnimatorHelper(anim, target); return anim; } public static ObjectAnimator ofPropertyValuesHolder(Object target, View view, PropertyValuesHolder... values) { ObjectAnimator anim = new ObjectAnimator(); anim.setTarget(target); anim.setValues(values); cancelOnDestroyActivity(anim); new FirstFrameAnimatorHelper(anim, view); return anim; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public static ValueAnimator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius) { ValueAnimator anim = UiThreadCircularReveal.createCircularReveal(view, centerX, centerY, startRadius, endRadius); new FirstFrameAnimatorHelper(anim, view); return anim; } }