/* * Copyright (C) 2009 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.launcher2; import android.os.Handler; import android.os.SystemClock; /** * Provides an animation between 0.0f and 1.0f over a given duration. */ class SymmetricalLinearTween { private static final int FPS = 30; private static final int FRAME_TIME = 1000 / FPS; Handler mHandler; int mDuration; TweenCallback mCallback; boolean mRunning; long mBase; boolean mDirection; float mValue; /** * @param duration milliseconds duration * @param callback callbacks */ public SymmetricalLinearTween(boolean initial, int duration, TweenCallback callback) { mValue = initial ? 1.0f : 0.0f; mDirection = initial; mDuration = duration; mCallback = callback; mHandler = new Handler(); } /** * Starts the tweening. * * @param direction If direction is true, the value goes towards 1.0f. If direction * is false, the value goes towards 0.0f. */ public void start(boolean direction) { start(direction, SystemClock.uptimeMillis()); } /** * Starts the tweening. * * @param direction If direction is true, the value goes towards 1.0f. If direction * is false, the value goes towards 0.0f. * @param baseTime The time to use as zero for this animation, in the * {@link SystemClock.uptimeMillis} time base. This allows you to * synchronize multiple animations. */ public void start(boolean direction, long baseTime) { if (direction != mDirection) { if (!mRunning) { mBase = baseTime; mRunning = true; mCallback.onTweenStarted(); long next = SystemClock.uptimeMillis() + FRAME_TIME; mHandler.postAtTime(mTick, next); } else { // reverse direction long now = SystemClock.uptimeMillis(); long diff = now - mBase; mBase = now + diff - mDuration; } mDirection = direction; } } Runnable mTick = new Runnable() { public void run() { long base = mBase; long now = SystemClock.uptimeMillis(); long diff = now-base; int duration = mDuration; float val = diff/(float)duration; if (!mDirection) { val = 1.0f - val; } if (val > 1.0f) { val = 1.0f; } else if (val < 0.0f) { val = 0.0f; } float old = mValue; mValue = val; mCallback.onTweenValueChanged(val, old); int frame = (int)(diff / FRAME_TIME); long next = base + ((frame+1)*FRAME_TIME); if (diff < duration) { mHandler.postAtTime(this, next); } if (diff >= duration) { mCallback.onTweenFinished(); mRunning = false; } } }; }