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