1/* 2 * Copyright (C) 2009 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 com.android.launcher2; 18 19import android.os.Handler; 20import android.os.SystemClock; 21 22/** 23 * Provides an animation between 0.0f and 1.0f over a given duration. 24 */ 25class SymmetricalLinearTween { 26 27 private static final int FPS = 30; 28 private static final int FRAME_TIME = 1000 / FPS; 29 30 Handler mHandler; 31 int mDuration; 32 TweenCallback mCallback; 33 34 boolean mRunning; 35 long mBase; 36 boolean mDirection; 37 float mValue; 38 39 /** 40 * @param duration milliseconds duration 41 * @param callback callbacks 42 */ 43 public SymmetricalLinearTween(boolean initial, int duration, TweenCallback callback) { 44 mValue = initial ? 1.0f : 0.0f; 45 mDirection = initial; 46 mDuration = duration; 47 mCallback = callback; 48 mHandler = new Handler(); 49 } 50 51 /** 52 * Starts the tweening. 53 * 54 * @param direction If direction is true, the value goes towards 1.0f. If direction 55 * is false, the value goes towards 0.0f. 56 */ 57 public void start(boolean direction) { 58 start(direction, SystemClock.uptimeMillis()); 59 } 60 61 /** 62 * Starts the tweening. 63 * 64 * @param direction If direction is true, the value goes towards 1.0f. If direction 65 * is false, the value goes towards 0.0f. 66 * @param baseTime The time to use as zero for this animation, in the 67 * {@link SystemClock.uptimeMillis} time base. This allows you to 68 * synchronize multiple animations. 69 */ 70 public void start(boolean direction, long baseTime) { 71 if (direction != mDirection) { 72 if (!mRunning) { 73 mBase = baseTime; 74 mRunning = true; 75 mCallback.onTweenStarted(); 76 long next = SystemClock.uptimeMillis() + FRAME_TIME; 77 mHandler.postAtTime(mTick, next); 78 } else { 79 // reverse direction 80 long now = SystemClock.uptimeMillis(); 81 long diff = now - mBase; 82 mBase = now + diff - mDuration; 83 } 84 mDirection = direction; 85 } 86 } 87 88 Runnable mTick = new Runnable() { 89 public void run() { 90 long base = mBase; 91 long now = SystemClock.uptimeMillis(); 92 long diff = now-base; 93 int duration = mDuration; 94 float val = diff/(float)duration; 95 if (!mDirection) { 96 val = 1.0f - val; 97 } 98 if (val > 1.0f) { 99 val = 1.0f; 100 } else if (val < 0.0f) { 101 val = 0.0f; 102 } 103 float old = mValue; 104 mValue = val; 105 mCallback.onTweenValueChanged(val, old); 106 int frame = (int)(diff / FRAME_TIME); 107 long next = base + ((frame+1)*FRAME_TIME); 108 if (diff < duration) { 109 mHandler.postAtTime(this, next); 110 } 111 if (diff >= duration) { 112 mCallback.onTweenFinished(); 113 mRunning = false; 114 } 115 } 116 }; 117} 118 119