1b505074e8273887fbcd1e933738a42e770085fb8Jim Miller/* 2b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * Copyright (C) 2011 The Android Open Source Project 3b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * 4b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 5b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * you may not use this file except in compliance with the License. 6b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * You may obtain a copy of the License at 7b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * 8b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * http://www.apache.org/licenses/LICENSE-2.0 9b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * 10b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * Unless required by applicable law or agreed to in writing, software 11b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * distributed under the License is distributed on an "AS IS" BASIS, 12b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * See the License for the specific language governing permissions and 14b505074e8273887fbcd1e933738a42e770085fb8Jim Miller * limitations under the License. 15b505074e8273887fbcd1e933738a42e770085fb8Jim Miller */ 16b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 17b505074e8273887fbcd1e933738a42e770085fb8Jim Millerpackage com.android.internal.widget.multiwaveview; 18b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 19b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport java.util.ArrayList; 20b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport java.util.HashMap; 21bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Millerimport java.util.Iterator; 22bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Millerimport java.util.Map.Entry; 23b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 24b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport android.animation.Animator.AnimatorListener; 25bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Millerimport android.animation.Animator; 26bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Millerimport android.animation.AnimatorListenerAdapter; 27b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport android.animation.ObjectAnimator; 28b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport android.animation.PropertyValuesHolder; 29b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport android.animation.TimeInterpolator; 30b505074e8273887fbcd1e933738a42e770085fb8Jim Millerimport android.animation.ValueAnimator.AnimatorUpdateListener; 31bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Millerimport android.util.Log; 32b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 33b505074e8273887fbcd1e933738a42e770085fb8Jim Millerclass Tweener { 34b505074e8273887fbcd1e933738a42e770085fb8Jim Miller private static final String TAG = "Tweener"; 35bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller private static final boolean DEBUG = false; 36b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 37b505074e8273887fbcd1e933738a42e770085fb8Jim Miller ObjectAnimator animator; 38b505074e8273887fbcd1e933738a42e770085fb8Jim Miller private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>(); 39b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 40bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller public Tweener(ObjectAnimator anim) { 41b505074e8273887fbcd1e933738a42e770085fb8Jim Miller animator = anim; 42b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 43b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 44bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller private static void remove(Animator animator) { 45bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator(); 46bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller while (iter.hasNext()) { 47bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller Entry<Object, Tweener> entry = iter.next(); 48bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller if (entry.getValue().animator == animator) { 49bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey()) 50bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller + " sTweens.size() = " + sTweens.size()); 51bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller iter.remove(); 52bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller break; // an animator can only be attached to one object 53bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 54bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 55bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 56bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller 57b505074e8273887fbcd1e933738a42e770085fb8Jim Miller public static Tweener to(Object object, long duration, Object... vars) { 58b505074e8273887fbcd1e933738a42e770085fb8Jim Miller long delay = 0; 59b505074e8273887fbcd1e933738a42e770085fb8Jim Miller AnimatorUpdateListener updateListener = null; 60b505074e8273887fbcd1e933738a42e770085fb8Jim Miller AnimatorListener listener = null; 61b505074e8273887fbcd1e933738a42e770085fb8Jim Miller TimeInterpolator interpolator = null; 62b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 63b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // Iterate through arguments and discover properties to animate 64b505074e8273887fbcd1e933738a42e770085fb8Jim Miller ArrayList<PropertyValuesHolder> props = new ArrayList<PropertyValuesHolder>(vars.length/2); 65b505074e8273887fbcd1e933738a42e770085fb8Jim Miller for (int i = 0; i < vars.length; i+=2) { 66b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if (!(vars[i] instanceof String)) { 67b505074e8273887fbcd1e933738a42e770085fb8Jim Miller throw new IllegalArgumentException("Key must be a string: " + vars[i]); 68b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 69b505074e8273887fbcd1e933738a42e770085fb8Jim Miller String key = (String) vars[i]; 70b505074e8273887fbcd1e933738a42e770085fb8Jim Miller Object value = vars[i+1]; 71b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if ("simultaneousTween".equals(key)) { 72b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // TODO 73b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else if ("ease".equals(key)) { 74b505074e8273887fbcd1e933738a42e770085fb8Jim Miller interpolator = (TimeInterpolator) value; // TODO: multiple interpolators? 75b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else if ("onUpdate".equals(key) || "onUpdateListener".equals(key)) { 76b505074e8273887fbcd1e933738a42e770085fb8Jim Miller updateListener = (AnimatorUpdateListener) value; 77b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else if ("onComplete".equals(key) || "onCompleteListener".equals(key)) { 78b505074e8273887fbcd1e933738a42e770085fb8Jim Miller listener = (AnimatorListener) value; 79b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else if ("delay".equals(key)) { 80b505074e8273887fbcd1e933738a42e770085fb8Jim Miller delay = ((Number) value).longValue(); 81b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else if ("syncWith".equals(key)) { 82b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // TODO 8370832a3d77d90f09fb7ba27612c9cbec6a92abe6Jim Miller } else if (value instanceof float[]) { 8470832a3d77d90f09fb7ba27612c9cbec6a92abe6Jim Miller props.add(PropertyValuesHolder.ofFloat(key, 8570832a3d77d90f09fb7ba27612c9cbec6a92abe6Jim Miller ((float[])value)[0], ((float[])value)[1])); 86a073e570789e5b49e8339af44516444b13db4428Jim Miller } else if (value instanceof int[]) { 87a073e570789e5b49e8339af44516444b13db4428Jim Miller props.add(PropertyValuesHolder.ofInt(key, 88a073e570789e5b49e8339af44516444b13db4428Jim Miller ((int[])value)[0], ((int[])value)[1])); 89b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else if (value instanceof Number) { 90b505074e8273887fbcd1e933738a42e770085fb8Jim Miller float floatValue = ((Number)value).floatValue(); 91b505074e8273887fbcd1e933738a42e770085fb8Jim Miller props.add(PropertyValuesHolder.ofFloat(key, floatValue)); 92b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else { 93b505074e8273887fbcd1e933738a42e770085fb8Jim Miller throw new IllegalArgumentException( 9470832a3d77d90f09fb7ba27612c9cbec6a92abe6Jim Miller "Bad argument for key \"" + key + "\" with value " + value.getClass()); 95b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 96b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 97b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 98b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // Re-use existing tween, if present 99b505074e8273887fbcd1e933738a42e770085fb8Jim Miller Tweener tween = sTweens.get(object); 100bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller ObjectAnimator anim = null; 101b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if (tween == null) { 102bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim = ObjectAnimator.ofPropertyValuesHolder(object, 103b505074e8273887fbcd1e933738a42e770085fb8Jim Miller props.toArray(new PropertyValuesHolder[props.size()])); 104bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller tween = new Tweener(anim); 105b505074e8273887fbcd1e933738a42e770085fb8Jim Miller sTweens.put(object, tween); 106bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller if (DEBUG) Log.v(TAG, "Added new Tweener " + tween); 107b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } else { 108bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim = sTweens.get(object).animator; 109bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller replace(props, object); // Cancel all animators for given object 110b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 111b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 112b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if (interpolator != null) { 113bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.setInterpolator(interpolator); 114b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 115b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 116b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // Update animation with properties discovered in loop above 117bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.setStartDelay(delay); 118bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.setDuration(duration); 119b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if (updateListener != null) { 120bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.removeAllUpdateListeners(); // There should be only one 121bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.addUpdateListener(updateListener); 122b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 123b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if (listener != null) { 124bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.removeAllListeners(); // There should be only one. 125bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.addListener(listener); 126b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 127bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller anim.addListener(mCleanupListener); 128b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 129b505074e8273887fbcd1e933738a42e770085fb8Jim Miller return tween; 130b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 131b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 132b505074e8273887fbcd1e933738a42e770085fb8Jim Miller Tweener from(Object object, long duration, Object... vars) { 133b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // TODO: for v of vars 134b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // toVars[v] = object[v] 135b505074e8273887fbcd1e933738a42e770085fb8Jim Miller // object[v] = vars[v] 136b505074e8273887fbcd1e933738a42e770085fb8Jim Miller return Tweener.to(object, duration, vars); 137b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 138b505074e8273887fbcd1e933738a42e770085fb8Jim Miller 139bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller // Listener to watch for completed animations and remove them. 140bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() { 141bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller 142bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller @Override 143bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller public void onAnimationEnd(Animator animation) { 144bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller remove(animation); 145bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 146bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller 147bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller @Override 148bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller public void onAnimationCancel(Animator animation) { 149bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller remove(animation); 150bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 151bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller }; 152bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller 153bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller public static void reset() { 154bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller if (DEBUG) { 155bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller Log.v(TAG, "Reset()"); 156bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller if (sTweens.size() > 0) { 157bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller Log.v(TAG, "Cleaning up " + sTweens.size() + " animations"); 158bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 159bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 160bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller sTweens.clear(); 161bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } 162bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller 163bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) { 164b505074e8273887fbcd1e933738a42e770085fb8Jim Miller for (final Object killobject : args) { 165b505074e8273887fbcd1e933738a42e770085fb8Jim Miller Tweener tween = sTweens.get(killobject); 166b505074e8273887fbcd1e933738a42e770085fb8Jim Miller if (tween != null) { 167bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller tween.animator.cancel(); 168bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller if (props != null) { 169bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller tween.animator.setValues( 170bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller props.toArray(new PropertyValuesHolder[props.size()])); 171bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller } else { 172bf591ff682f14db7ba7b3554897e9cdcf245da59Jim Miller sTweens.remove(tween); 173b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 174b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 175b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 176b505074e8273887fbcd1e933738a42e770085fb8Jim Miller } 177b505074e8273887fbcd1e933738a42e770085fb8Jim Miller} 178