1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.animation; 18 19import android.view.View; 20 21import java.util.ArrayList; 22import java.util.List; 23 24/** 25 * Provides similar functionality to Animators on platforms prior to Honeycomb. 26 * <p> 27 * This is not a fully implemented API which is why it is not public. 28 * 29 * @hide 30 */ 31class DonutAnimatorCompatProvider implements AnimatorProvider { 32 33 @Override 34 public ValueAnimatorCompat emptyValueAnimator() { 35 return new DonutFloatValueAnimator(); 36 } 37 38 private static class DonutFloatValueAnimator implements ValueAnimatorCompat { 39 40 List<AnimatorListenerCompat> mListeners = new ArrayList<AnimatorListenerCompat>(); 41 List<AnimatorUpdateListenerCompat> mUpdateListeners 42 = new ArrayList<AnimatorUpdateListenerCompat>(); 43 View mTarget; 44 private long mStartTime; 45 private long mDuration = 200; 46 private float mFraction = 0f; 47 48 private boolean mStarted = false; 49 private boolean mEnded = false; 50 51 public DonutFloatValueAnimator() { 52 } 53 54 private Runnable mLoopRunnable = new Runnable() { 55 @Override 56 public void run() { 57 long dt = getTime() - mStartTime; 58 float fraction = dt * 1f / mDuration; 59 if (fraction > 1f || mTarget.getParent() == null) { 60 fraction = 1f; 61 } 62 mFraction = fraction; 63 notifyUpdateListeners(); 64 if (mFraction >= 1f) { 65 dispatchEnd(); 66 } else { 67 mTarget.postDelayed(mLoopRunnable, 16); 68 } 69 } 70 }; 71 72 private void notifyUpdateListeners() { 73 for (int i = mUpdateListeners.size() - 1; i >= 0; i--) { 74 mUpdateListeners.get(i).onAnimationUpdate(this); 75 } 76 } 77 78 @Override 79 public void setTarget(View view) { 80 mTarget = view; 81 } 82 83 @Override 84 public void addListener(AnimatorListenerCompat listener) { 85 mListeners.add(listener); 86 } 87 88 @Override 89 public void setDuration(long duration) { 90 if (!mStarted) { 91 mDuration = duration; 92 } 93 } 94 95 @Override 96 public void start() { 97 if (mStarted) { 98 return; 99 } 100 mStarted = true; 101 dispatchStart(); 102 mFraction = 0f; 103 mStartTime = getTime(); 104 mTarget.postDelayed(mLoopRunnable, 16); 105 } 106 107 private long getTime() { 108 return mTarget.getDrawingTime(); 109 } 110 111 private void dispatchStart() { 112 for (int i = mListeners.size() - 1; i >= 0; i--) { 113 mListeners.get(i).onAnimationStart(this); 114 } 115 } 116 117 private void dispatchEnd() { 118 for (int i = mListeners.size() - 1; i >= 0; i--) { 119 mListeners.get(i).onAnimationEnd(this); 120 } 121 } 122 123 private void dispatchCancel() { 124 for (int i = mListeners.size() - 1; i >= 0; i--) { 125 mListeners.get(i).onAnimationCancel(this); 126 } 127 } 128 129 @Override 130 public void cancel() { 131 if (mEnded) { 132 return; 133 } 134 mEnded = true; 135 if (mStarted) { 136 dispatchCancel(); 137 } 138 dispatchEnd(); 139 } 140 141 @Override 142 public void addUpdateListener(AnimatorUpdateListenerCompat animatorUpdateListener) { 143 mUpdateListeners.add(animatorUpdateListener); 144 } 145 146 @Override 147 public float getAnimatedFraction() { 148 return mFraction; 149 } 150 } 151 152 @Override 153 public void clearInterpolator(View view) { 154 } 155} 156