16772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang/* 26772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Copyright (C) 2006 The Android Open Source Project 36772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 46772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License"); 56772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * you may not use this file except in compliance with the License. 66772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * You may obtain a copy of the License at 76772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 86772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * http://www.apache.org/licenses/LICENSE-2.0 96772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 106772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Unless required by applicable law or agreed to in writing, software 116772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS, 126772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * See the License for the specific language governing permissions and 146772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * limitations under the License. 156772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 166772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 176772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changpackage com.android.gallery3d.common; 186772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 196772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.content.Context; 206772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.hardware.SensorManager; 216772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.os.Build; 226772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.util.FloatMath; 236772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.view.ViewConfiguration; 246772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.view.animation.AnimationUtils; 256772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.view.animation.Interpolator; 266772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 276772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 286772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang/** 296772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * This class encapsulates scrolling. The duration of the scroll 306772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * can be passed in the constructor and specifies the maximum time that 316772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * the scrolling animation should take. Past this time, the scrolling is 326772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * automatically moved to its final stage and computeScrollOffset() 336772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * will always return false to indicate that scrolling is over. 346772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 356772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changpublic class Scroller { 366772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mMode; 376772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 386772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mStartX; 396772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mStartY; 406772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mFinalX; 416772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mFinalY; 426772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 436772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mMinX; 446772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mMaxX; 456772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mMinY; 466772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mMaxY; 476772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 486772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mCurrX; 496772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mCurrY; 506772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private long mStartTime; 516772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private int mDuration; 526772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private float mDurationReciprocal; 536772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private float mDeltaX; 546772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private float mDeltaY; 556772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private boolean mFinished; 566772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private Interpolator mInterpolator; 576772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private boolean mFlywheel; 586772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 596772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private float mVelocity; 606772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 616772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static final int DEFAULT_DURATION = 250; 626772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static final int SCROLL_MODE = 0; 636772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static final int FLING_MODE = 1; 646772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 656772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9)); 666772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static float ALPHA = 800; // pixels / seconds 676772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance) 686772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static float END_TENSION = 1.0f - START_TENSION; 696772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static final int NB_SAMPLES = 100; 706772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static final float[] SPLINE = new float[NB_SAMPLES + 1]; 716772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 726772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private float mDeceleration; 736772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private final float mPpi; 746772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 756772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang static { 766772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float x_min = 0.0f; 776772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang for (int i = 0; i <= NB_SAMPLES; i++) { 786772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float t = (float) i / NB_SAMPLES; 796772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float x_max = 1.0f; 806772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float x, tx, coef; 816772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang while (true) { 826772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x = x_min + (x_max - x_min) / 2.0f; 836772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang coef = 3.0f * x * (1.0f - x); 846772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x; 856772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (Math.abs(tx - t) < 1E-5) break; 866772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (tx > t) x_max = x; 876772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang else x_min = x; 886772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 896772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float d = coef + x * x * x; 906772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang SPLINE[i] = d; 916772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 926772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang SPLINE[NB_SAMPLES] = 1.0f; 936772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 946772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // This controls the viscous fluid effect (how much of it) 956772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang sViscousFluidScale = 8.0f; 966772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // must be set to 1.0 (used in viscousFluid()) 976772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang sViscousFluidNormalize = 1.0f; 986772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang sViscousFluidNormalize = 1.0f / viscousFluid(1.0f); 996772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1006772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1016772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static float sViscousFluidScale; 1026772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private static float sViscousFluidNormalize; 1036772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1046772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1056772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Create a Scroller with the default duration and interpolator. 1066772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1076772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public Scroller(Context context) { 1086772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang this(context, null); 1096772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1106772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1116772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1126772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Create a Scroller with the specified interpolator. If the interpolator is 1136772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * null, the default (viscous) interpolator will be used. "Flywheel" behavior will 1146772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * be in effect for apps targeting Honeycomb or newer. 1156772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1166772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public Scroller(Context context, Interpolator interpolator) { 1176772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang this(context, interpolator, 1186772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB); 1196772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1206772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1216772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1226772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Create a Scroller with the specified interpolator. If the interpolator is 1236772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * null, the default (viscous) interpolator will be used. Specify whether or 1246772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * not to support progressive "flywheel" behavior in flinging. 1256772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1266772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public Scroller(Context context, Interpolator interpolator, boolean flywheel) { 1276772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = true; 1286772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mInterpolator = interpolator; 1296772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mPpi = context.getResources().getDisplayMetrics().density * 160.0f; 1306772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction()); 1316772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFlywheel = flywheel; 1326772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1336772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1346772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1356772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * The amount of friction applied to flings. The default value 1366772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * is {@link ViewConfiguration#getScrollFriction}. 1376772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1386772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param friction A scalar dimension-less value representing the coefficient of 1396772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * friction. 1406772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1416772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final void setFriction(float friction) { 1426772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDeceleration = computeDeceleration(friction); 1436772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1446772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1456772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang private float computeDeceleration(float friction) { 1466772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return SensorManager.GRAVITY_EARTH // g (m/s^2) 1476772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 39.37f // inch/meter 1486772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * mPpi // pixels per inch 1496772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * friction; 1506772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1516772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1526772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1536772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1546772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns whether the scroller has finished scrolling. 1556772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1566772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return True if the scroller has finished scrolling, false otherwise. 1576772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1586772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final boolean isFinished() { 1596772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mFinished; 1606772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1616772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1626772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1636772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Force the finished field to a particular value. 1646772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1656772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param finished The new finished value. 1666772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1676772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final void forceFinished(boolean finished) { 1686772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = finished; 1696772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1706772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1716772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1726772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns how long the scroll event will take, in milliseconds. 1736772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1746772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The duration of the scroll in milliseconds. 1756772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1766772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getDuration() { 1776772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mDuration; 1786772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1796772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1806772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1816772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns the current X offset in the scroll. 1826772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1836772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The new X offset as an absolute distance from the origin. 1846772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1856772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getCurrX() { 1866772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mCurrX; 1876772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1886772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1896772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1906772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns the current Y offset in the scroll. 1916772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 1926772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The new Y offset as an absolute distance from the origin. 1936772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 1946772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getCurrY() { 1956772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mCurrY; 1966772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 1976772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 1986772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 1996772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns the current velocity. 2006772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 2016772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The original velocity less the deceleration. Result may be 2026772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * negative. 2036772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 2046772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public float getCurrVelocity() { 2056772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mVelocity - mDeceleration * timePassed() / 2000.0f; 2066772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2076772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2086772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 2096772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns the start X offset in the scroll. 2106772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 2116772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The start X offset as an absolute distance from the origin. 2126772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 2136772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getStartX() { 2146772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mStartX; 2156772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2166772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2176772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 2186772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns the start Y offset in the scroll. 2196772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 2206772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The start Y offset as an absolute distance from the origin. 2216772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 2226772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getStartY() { 2236772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mStartY; 2246772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2256772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2266772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 2276772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns where the scroll will end. Valid only for "fling" scrolls. 2286772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 2296772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The final X offset as an absolute distance from the origin. 2306772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 2316772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getFinalX() { 2326772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mFinalX; 2336772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2346772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2356772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 2366772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns where the scroll will end. Valid only for "fling" scrolls. 2376772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 2386772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The final Y offset as an absolute distance from the origin. 2396772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 2406772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public final int getFinalY() { 2416772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return mFinalY; 2426772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2436772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2446772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 2456772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Call this when you want to know the new location. If it returns true, 2466772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * the animation is not yet finished. loc will be altered to provide the 2476772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * new location. 2486772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 2496772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public boolean computeScrollOffset() { 2506772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (mFinished) { 2516772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return false; 2526772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2536772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2546772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); 2556772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2566772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (timePassed < mDuration) { 2576772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang switch (mMode) { 2586772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang case SCROLL_MODE: 2596772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float x = timePassed * mDurationReciprocal; 2606772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2616772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (mInterpolator == null) 2626772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x = viscousFluid(x); 2636772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang else 2646772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x = mInterpolator.getInterpolation(x); 2656772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2666772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrX = mStartX + Math.round(x * mDeltaX); 2676772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrY = mStartY + Math.round(x * mDeltaY); 2686772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang break; 2696772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang case FLING_MODE: 2706772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float t = (float) timePassed / mDuration; 2716772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final int index = (int) (NB_SAMPLES * t); 2726772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float t_inf = (float) index / NB_SAMPLES; 2736772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float t_sup = (float) (index + 1) / NB_SAMPLES; 2746772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float d_inf = SPLINE[index]; 2756772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float d_sup = SPLINE[index + 1]; 2766772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf); 2776772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2786772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX)); 2796772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // Pin to mMinX <= mCurrX <= mMaxX 2806772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrX = Math.min(mCurrX, mMaxX); 2816772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrX = Math.max(mCurrX, mMinX); 2826772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2836772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY)); 2846772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // Pin to mMinY <= mCurrY <= mMaxY 2856772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrY = Math.min(mCurrY, mMaxY); 2866772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrY = Math.max(mCurrY, mMinY); 2876772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2886772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (mCurrX == mFinalX && mCurrY == mFinalY) { 2896772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = true; 2906772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2916772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 2926772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang break; 2936772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2946772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 2956772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang else { 2966772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrX = mFinalX; 2976772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrY = mFinalY; 2986772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = true; 2996772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 3006772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return true; 3016772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 3026772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3036772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 3046772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Start scrolling by providing a starting point and the distance to travel. 3056772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * The scroll will use the default value of 250 milliseconds for the 3066772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * duration. 3076772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 3086772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param startX Starting horizontal scroll offset in pixels. Positive 3096772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * numbers will scroll the content to the left. 3106772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param startY Starting vertical scroll offset in pixels. Positive numbers 3116772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * will scroll the content up. 3126772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param dx Horizontal distance to travel. Positive numbers will scroll the 3136772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * content to the left. 3146772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param dy Vertical distance to travel. Positive numbers will scroll the 3156772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * content up. 3166772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 3176772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void startScroll(int startX, int startY, int dx, int dy) { 3186772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang startScroll(startX, startY, dx, dy, DEFAULT_DURATION); 3196772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 3206772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3216772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 3226772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Start scrolling by providing a starting point and the distance to travel. 3236772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 3246772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param startX Starting horizontal scroll offset in pixels. Positive 3256772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * numbers will scroll the content to the left. 3266772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param startY Starting vertical scroll offset in pixels. Positive numbers 3276772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * will scroll the content up. 3286772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param dx Horizontal distance to travel. Positive numbers will scroll the 3296772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * content to the left. 3306772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param dy Vertical distance to travel. Positive numbers will scroll the 3316772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * content up. 3326772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param duration Duration of the scroll in milliseconds. 3336772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 3346772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void startScroll(int startX, int startY, int dx, int dy, int duration) { 3356772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mMode = SCROLL_MODE; 3366772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = false; 3376772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDuration = duration; 3386772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mStartTime = AnimationUtils.currentAnimationTimeMillis(); 3396772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mStartX = startX; 3406772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mStartY = startY; 3416772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalX = startX + dx; 3426772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalY = startY + dy; 3436772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDeltaX = dx; 3446772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDeltaY = dy; 3457817979db0c52ffeacb951625b1e821eba303285Ahbong Chang mDurationReciprocal = 1.0f / mDuration; 3466772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 3476772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3486772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 3496772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Start scrolling based on a fling gesture. The distance travelled will 3506772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * depend on the initial velocity of the fling. 3516772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 3526772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param startX Starting point of the scroll (X) 3536772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param startY Starting point of the scroll (Y) 3546772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param velocityX Initial velocity of the fling (X) measured in pixels per 3556772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * second. 3566772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param velocityY Initial velocity of the fling (Y) measured in pixels per 3576772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * second 3586772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param minX Minimum X value. The scroller will not scroll past this 3596772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * point. 3606772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param maxX Maximum X value. The scroller will not scroll past this 3616772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * point. 3626772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param minY Minimum Y value. The scroller will not scroll past this 3636772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * point. 3646772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param maxY Maximum Y value. The scroller will not scroll past this 3656772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * point. 3666772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 3676772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void fling(int startX, int startY, int velocityX, int velocityY, 3686772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang int minX, int maxX, int minY, int maxY) { 3696772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // Continue a scroll or fling in progress 3706772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (mFlywheel && !mFinished) { 3716772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float oldVel = getCurrVelocity(); 3726772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3737817979db0c52ffeacb951625b1e821eba303285Ahbong Chang float dx = mFinalX - mStartX; 3747817979db0c52ffeacb951625b1e821eba303285Ahbong Chang float dy = mFinalY - mStartY; 3756772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float hyp = FloatMath.sqrt(dx * dx + dy * dy); 3766772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3776772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float ndx = dx / hyp; 3786772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float ndy = dy / hyp; 3796772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3806772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float oldVelocityX = ndx * oldVel; 3816772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float oldVelocityY = ndy * oldVel; 3826772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (Math.signum(velocityX) == Math.signum(oldVelocityX) && 3836772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang Math.signum(velocityY) == Math.signum(oldVelocityY)) { 3846772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang velocityX += oldVelocityX; 3856772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang velocityY += oldVelocityY; 3866772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 3876772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 3886772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3896772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mMode = FLING_MODE; 3906772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = false; 3916772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3926772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY); 3936772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 3946772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mVelocity = velocity; 3956772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang final double l = Math.log(START_TENSION * velocity / ALPHA); 3966772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0))); 3976772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mStartTime = AnimationUtils.currentAnimationTimeMillis(); 3986772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mStartX = startX; 3996772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mStartY = startY; 4006772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4016772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float coeffX = velocity == 0 ? 1.0f : velocityX / velocity; 4026772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float coeffY = velocity == 0 ? 1.0f : velocityY / velocity; 4036772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4046772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang int totalDistance = 4056772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang (int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l)); 4066772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4076772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mMinX = minX; 4086772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mMaxX = maxX; 4096772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mMinY = minY; 4106772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mMaxY = maxY; 4116772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4126772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalX = startX + Math.round(totalDistance * coeffX); 4136772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // Pin to mMinX <= mFinalX <= mMaxX 4146772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalX = Math.min(mFinalX, mMaxX); 4156772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalX = Math.max(mFinalX, mMinX); 4166772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4176772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalY = startY + Math.round(totalDistance * coeffY); 4186772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang // Pin to mMinY <= mFinalY <= mMaxY 4196772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalY = Math.min(mFinalY, mMaxY); 4206772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalY = Math.max(mFinalY, mMinY); 4216772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4226772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4236772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang static float viscousFluid(float x) 4246772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang { 4256772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x *= sViscousFluidScale; 4266772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang if (x < 1.0f) { 4276772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x -= (1.0f - (float)Math.exp(-x)); 4286772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } else { 4296772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang float start = 0.36787944117f; // 1/e == exp(-1) 4306772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x = 1.0f - (float)Math.exp(1.0f - x); 4316772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x = start + x * (1.0f - start); 4326772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4336772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang x *= sViscousFluidNormalize; 4346772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return x; 4356772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4366772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4376772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 4386772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Stops the animation. Contrary to {@link #forceFinished(boolean)}, 4396772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * aborting the animating cause the scroller to move to the final x and y 4406772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * position 4416772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 4426772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #forceFinished(boolean) 4436772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 4446772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void abortAnimation() { 4456772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrX = mFinalX; 4466772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mCurrY = mFinalY; 4476772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = true; 4486772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4496772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4506772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 4516772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Extend the scroll animation. This allows a running animation to scroll 4526772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}. 4536772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 4546772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param extend Additional time to scroll in milliseconds. 4556772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #setFinalX(int) 4566772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #setFinalY(int) 4576772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 4586772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void extendDuration(int extend) { 4596772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang int passed = timePassed(); 4606772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDuration = passed + extend; 4616772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDurationReciprocal = 1.0f / mDuration; 4626772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = false; 4636772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4646772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4656772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 4666772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Returns the time elapsed since the beginning of the scrolling. 4676772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 4686772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @return The elapsed time in milliseconds. 4696772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 4706772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public int timePassed() { 4716772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); 4726772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4736772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4746772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 4756772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Sets the final position (X) for this scroller. 4766772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 4776772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param newX The new X offset as an absolute distance from the origin. 4786772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #extendDuration(int) 4796772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #setFinalY(int) 4806772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 4816772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void setFinalX(int newX) { 4826772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalX = newX; 4836772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDeltaX = mFinalX - mStartX; 4846772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = false; 4856772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4866772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 4876772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 4886772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * Sets the final position (Y) for this scroller. 4896772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * 4906772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @param newY The new Y offset as an absolute distance from the origin. 4916772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #extendDuration(int) 4926772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @see #setFinalX(int) 4936772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 4946772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public void setFinalY(int newY) { 4956772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinalY = newY; 4966772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mDeltaY = mFinalY - mStartY; 4976772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang mFinished = false; 4986772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 4996772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang 5006772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang /** 5016772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang * @hide 5026772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang */ 5036772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang public boolean isScrollingInDirection(float xvel, float yvel) { 5046772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) && 5056772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang Math.signum(yvel) == Math.signum(mFinalY - mStartY); 5066772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang } 5076772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang} 508