19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 20c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottierimport android.hardware.SensorManager; 21d348bb4feff72d047a1037537be2d334a00c380cGilles Debunneimport android.os.Build; 22d348bb4feff72d047a1037537be2d334a00c380cGilles Debunneimport android.util.FloatMath; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewConfiguration; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.AnimationUtils; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.Interpolator; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class encapsulates scrolling. The duration of the scroll 309d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * can be passed in the constructor and specifies the maximum time that 319d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * the scrolling animation should take. Past this time, the scrolling is 329d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * automatically moved to its final stage and computeScrollOffset() 339d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * will always return false to indicate that scrolling is over. 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Scroller { 366579b0b4ac0e781efab044aaaf3f66447cf5e067Adam Powell private int mMode; 3752964243dc95f74ac2ab9a96d031a36931a11931Gilles Debunne 389d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mStartX; 399d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mStartY; 409d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mFinalX; 419d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mFinalY; 429d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 439d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mMinX; 449d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mMaxX; 459d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mMinY; 469d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mMaxY; 479d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 489d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mCurrX; 499d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mCurrY; 509d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private long mStartTime; 519d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private int mDuration; 529d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private float mDurationReciprocal; 539d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private float mDeltaX; 549d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private float mDeltaY; 559d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private boolean mFinished; 569d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private Interpolator mInterpolator; 57d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne private boolean mFlywheel; 589d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 599d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell private float mVelocity; 6052964243dc95f74ac2ab9a96d031a36931a11931Gilles Debunne 616579b0b4ac0e781efab044aaaf3f66447cf5e067Adam Powell private static final int DEFAULT_DURATION = 250; 626579b0b4ac0e781efab044aaaf3f66447cf5e067Adam Powell private static final int SCROLL_MODE = 0; 636579b0b4ac0e781efab044aaaf3f66447cf5e067Adam Powell private static final int FLING_MODE = 1; 6452964243dc95f74ac2ab9a96d031a36931a11931Gilles Debunne 65d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9)); 6604cdb78c6a2ac66505d0b29033353cfd7e2c3d78Gilles Debunne private static float ALPHA = 800; // pixels / seconds 67d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance) 68d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne private static float END_TENSION = 1.0f - START_TENSION; 69d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne private static final int NB_SAMPLES = 100; 70d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne private static final float[] SPLINE = new float[NB_SAMPLES + 1]; 71d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 724bede9e425875542976a422222510fa4056a8339Romain Guy private float mDeceleration; 734bede9e425875542976a422222510fa4056a8339Romain Guy private final float mPpi; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne static { 76d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float x_min = 0.0f; 77d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne for (int i = 0; i <= NB_SAMPLES; i++) { 78d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float t = (float) i / NB_SAMPLES; 79d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float x_max = 1.0f; 80d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float x, tx, coef; 81d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne while (true) { 82d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne x = x_min + (x_max - x_min) / 2.0f; 83d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne coef = 3.0f * x * (1.0f - x); 84d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x; 85d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne if (Math.abs(tx - t) < 1E-5) break; 86d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne if (tx > t) x_max = x; 87d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne else x_min = x; 88d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 89d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float d = coef + x * x * x; 90d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne SPLINE[i] = d; 91d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 92d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne SPLINE[NB_SAMPLES] = 1.0f; 93637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 94637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell // This controls the viscous fluid effect (how much of it) 95637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell sViscousFluidScale = 8.0f; 96637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell // must be set to 1.0 (used in viscousFluid()) 97637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell sViscousFluidNormalize = 1.0f; 98637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell sViscousFluidNormalize = 1.0f / viscousFluid(1.0f); 99d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 100d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 101637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell private static float sViscousFluidScale; 102637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell private static float sViscousFluidNormalize; 103637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1059d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Create a Scroller with the default duration and interpolator. 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Scroller(Context context) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 111637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell /** 112637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * Create a Scroller with the specified interpolator. If the interpolator is 113637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * null, the default (viscous) interpolator will be used. "Flywheel" behavior will 114637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * be in effect for apps targeting Honeycomb or newer. 115637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell */ 116d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne public Scroller(Context context, Interpolator interpolator) { 117d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne this(context, interpolator, 118d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB); 119d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 120d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a Scroller with the specified interpolator. If the interpolator is 123637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * null, the default (viscous) interpolator will be used. Specify whether or 124637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * not to support progressive "flywheel" behavior in flinging. 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 126d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne public Scroller(Context context, Interpolator interpolator, boolean flywheel) { 1279d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = true; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInterpolator = interpolator; 1294bede9e425875542976a422222510fa4056a8339Romain Guy mPpi = context.getResources().getDisplayMetrics().density * 160.0f; 1304bede9e425875542976a422222510fa4056a8339Romain Guy mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction()); 131d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne mFlywheel = flywheel; 1324bede9e425875542976a422222510fa4056a8339Romain Guy } 1334bede9e425875542976a422222510fa4056a8339Romain Guy 1344bede9e425875542976a422222510fa4056a8339Romain Guy /** 1354bede9e425875542976a422222510fa4056a8339Romain Guy * The amount of friction applied to flings. The default value 1364bede9e425875542976a422222510fa4056a8339Romain Guy * is {@link ViewConfiguration#getScrollFriction}. 1374bede9e425875542976a422222510fa4056a8339Romain Guy * 138d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne * @param friction A scalar dimension-less value representing the coefficient of 1394bede9e425875542976a422222510fa4056a8339Romain Guy * friction. 1404bede9e425875542976a422222510fa4056a8339Romain Guy */ 1414bede9e425875542976a422222510fa4056a8339Romain Guy public final void setFriction(float friction) { 142a655c635820425a4c98314c3ba02eb382229b45dRomain Guy mDeceleration = computeDeceleration(friction); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1449d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 1454bede9e425875542976a422222510fa4056a8339Romain Guy private float computeDeceleration(float friction) { 1464bede9e425875542976a422222510fa4056a8339Romain Guy return SensorManager.GRAVITY_EARTH // g (m/s^2) 1474bede9e425875542976a422222510fa4056a8339Romain Guy * 39.37f // inch/meter 1484bede9e425875542976a422222510fa4056a8339Romain Guy * mPpi // pixels per inch 1494bede9e425875542976a422222510fa4056a8339Romain Guy * friction; 1504bede9e425875542976a422222510fa4056a8339Romain Guy } 1514bede9e425875542976a422222510fa4056a8339Romain Guy 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns whether the scroller has finished scrolling. 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the scroller has finished scrolling, false otherwise. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final boolean isFinished() { 1599d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mFinished; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1619d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Force the finished field to a particular value. 1649d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param finished The new finished value. 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final void forceFinished(boolean finished) { 1689d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = finished; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns how long the scroll event will take, in milliseconds. 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The duration of the scroll in milliseconds. 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getDuration() { 1779d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mDuration; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1819d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Returns the current X offset in the scroll. 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The new X offset as an absolute distance from the origin. 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getCurrX() { 1869d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mCurrX; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1909d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Returns the current Y offset in the scroll. 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The new Y offset as an absolute distance from the origin. 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getCurrY() { 1959d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mCurrY; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 199278ce05b52a47a09d2177435b533f4ecb1b9c4daCary Clark * Returns the current velocity. 2009d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 2019d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * @return The original velocity less the deceleration. Result may be 2029d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * negative. 203278ce05b52a47a09d2177435b533f4ecb1b9c4daCary Clark */ 204278ce05b52a47a09d2177435b533f4ecb1b9c4daCary Clark public float getCurrVelocity() { 2059d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mVelocity - mDeceleration * timePassed() / 2000.0f; 206278ce05b52a47a09d2177435b533f4ecb1b9c4daCary Clark } 207278ce05b52a47a09d2177435b533f4ecb1b9c4daCary Clark 208278ce05b52a47a09d2177435b533f4ecb1b9c4daCary Clark /** 2099d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Returns the start X offset in the scroll. 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The start X offset as an absolute distance from the origin. 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getStartX() { 2149d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mStartX; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2169d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2189d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Returns the start Y offset in the scroll. 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The start Y offset as an absolute distance from the origin. 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getStartY() { 2239d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mStartY; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns where the scroll will end. Valid only for "fling" scrolls. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The final X offset as an absolute distance from the origin. 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getFinalX() { 2329d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mFinalX; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns where the scroll will end. Valid only for "fling" scrolls. 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The final Y offset as an absolute distance from the origin. 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final int getFinalY() { 2419d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return mFinalY; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2459d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Call this when you want to know the new location. If it returns true, 2469d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * the animation is not yet finished. loc will be altered to provide the 2479d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * new location. 2489d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell */ 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean computeScrollOffset() { 2509d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell if (mFinished) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); 2559d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 2569d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell if (timePassed < mDuration) { 2579d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell switch (mMode) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SCROLL_MODE: 259d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float x = timePassed * mDurationReciprocal; 2609d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 2619d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell if (mInterpolator == null) 2629d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell x = viscousFluid(x); 2639d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell else 2649d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell x = mInterpolator.getInterpolation(x); 2659d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 2669d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrX = mStartX + Math.round(x * mDeltaX); 2679d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrY = mStartY + Math.round(x * mDeltaY); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case FLING_MODE: 270d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float t = (float) timePassed / mDuration; 271d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final int index = (int) (NB_SAMPLES * t); 272d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float t_inf = (float) index / NB_SAMPLES; 273d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float t_sup = (float) (index + 1) / NB_SAMPLES; 274d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float d_inf = SPLINE[index]; 275d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float d_sup = SPLINE[index + 1]; 276d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf); 2779d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 278d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX)); 2799d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell // Pin to mMinX <= mCurrX <= mMaxX 2809d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrX = Math.min(mCurrX, mMaxX); 2819d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrX = Math.max(mCurrX, mMinX); 2829d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 283d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY)); 2849d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell // Pin to mMinY <= mCurrY <= mMaxY 2859d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrY = Math.min(mCurrY, mMaxY); 2869d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrY = Math.max(mCurrY, mMinY); 2871b088be8bb304e4ab7a1896d3ec3b9df9d9cf68eAdam Powell 2881b088be8bb304e4ab7a1896d3ec3b9df9d9cf68eAdam Powell if (mCurrX == mFinalX && mCurrY == mFinalY) { 2891b088be8bb304e4ab7a1896d3ec3b9df9d9cf68eAdam Powell mFinished = true; 2901b088be8bb304e4ab7a1896d3ec3b9df9d9cf68eAdam Powell } 2911b088be8bb304e4ab7a1896d3ec3b9df9d9cf68eAdam Powell 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2939d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell } 2949d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell } 2959d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell else { 2969d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrX = mFinalX; 2979d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrY = mFinalY; 2989d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = true; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start scrolling by providing a starting point and the distance to travel. 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The scroll will use the default value of 250 milliseconds for the 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * duration. 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startX Starting horizontal scroll offset in pixels. Positive 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * numbers will scroll the content to the left. 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startY Starting vertical scroll offset in pixels. Positive numbers 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will scroll the content up. 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dx Horizontal distance to travel. Positive numbers will scroll the 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content to the left. 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dy Vertical distance to travel. Positive numbers will scroll the 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content up. 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startScroll(int startX, int startY, int dx, int dy) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startScroll(startX, startY, dx, dy, DEFAULT_DURATION); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start scrolling by providing a starting point and the distance to travel. 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startX Starting horizontal scroll offset in pixels. Positive 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * numbers will scroll the content to the left. 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startY Starting vertical scroll offset in pixels. Positive numbers 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will scroll the content up. 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dx Horizontal distance to travel. Positive numbers will scroll the 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content to the left. 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dy Vertical distance to travel. Positive numbers will scroll the 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content up. 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param duration Duration of the scroll in milliseconds. 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startScroll(int startX, int startY, int dx, int dy, int duration) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMode = SCROLL_MODE; 3369d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = false; 3379d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mDuration = duration; 3389d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mStartTime = AnimationUtils.currentAnimationTimeMillis(); 3399d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mStartX = startX; 3409d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mStartY = startY; 3419d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalX = startX + dx; 3429d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalY = startY + dy; 3439d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mDeltaX = dx; 3449d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mDeltaY = dy; 345637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell mDurationReciprocal = 1.0f / (float) mDuration; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3499d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * Start scrolling based on a fling gesture. The distance travelled will 3509d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * depend on the initial velocity of the fling. 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startX Starting point of the scroll (X) 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startY Starting point of the scroll (Y) 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param velocityX Initial velocity of the fling (X) measured in pixels per 3559d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * second. 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param velocityY Initial velocity of the fling (Y) measured in pixels per 3579d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * second 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param minX Minimum X value. The scroller will not scroll past this 3599d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * point. 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param maxX Maximum X value. The scroller will not scroll past this 3619d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * point. 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param minY Minimum Y value. The scroller will not scroll past this 3639d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * point. 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param maxY Maximum Y value. The scroller will not scroll past this 3659d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * point. 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void fling(int startX, int startY, int velocityX, int velocityY, 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int minX, int maxX, int minY, int maxY) { 369d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne // Continue a scroll or fling in progress 370d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne if (mFlywheel && !mFinished) { 371d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float oldVel = getCurrVelocity(); 372d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 373d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float dx = (float) (mFinalX - mStartX); 374d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float dy = (float) (mFinalY - mStartY); 375d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float hyp = FloatMath.sqrt(dx * dx + dy * dy); 376d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 377d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float ndx = dx / hyp; 378d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float ndy = dy / hyp; 379d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 380d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float oldVelocityX = ndx * oldVel; 381d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float oldVelocityY = ndy * oldVel; 382d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne if (Math.signum(velocityX) == Math.signum(oldVelocityX) && 383d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne Math.signum(velocityY) == Math.signum(oldVelocityY)) { 384d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne velocityX += oldVelocityX; 385d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne velocityY += oldVelocityY; 386d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 387d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 388d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMode = FLING_MODE; 3909d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = false; 3919d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 392d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY); 3939d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 3949d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mVelocity = velocity; 395d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne final double l = Math.log(START_TENSION * velocity / ALPHA); 396d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0))); 3979d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mStartTime = AnimationUtils.currentAnimationTimeMillis(); 3989d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mStartX = startX; 3999d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mStartY = startY; 4009d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 401637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell float coeffX = velocity == 0 ? 1.0f : velocityX / velocity; 402637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell float coeffY = velocity == 0 ? 1.0f : velocityY / velocity; 4039d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 404d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne int totalDistance = 405d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne (int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l)); 4069d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 4079d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mMinX = minX; 4089d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mMaxX = maxX; 4099d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mMinY = minY; 4109d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mMaxY = maxY; 411d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 412637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell mFinalX = startX + Math.round(totalDistance * coeffX); 4139d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell // Pin to mMinX <= mFinalX <= mMaxX 4149d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalX = Math.min(mFinalX, mMaxX); 4159d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalX = Math.max(mFinalX, mMinX); 4169d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 417637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell mFinalY = startY + Math.round(totalDistance * coeffY); 4189d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell // Pin to mMinY <= mFinalY <= mMaxY 4199d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalY = Math.min(mFinalY, mMaxY); 4209d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalY = Math.max(mFinalY, mMinY); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 423637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell static float viscousFluid(float x) 4249d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell { 425637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell x *= sViscousFluidScale; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x < 1.0f) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x -= (1.0f - (float)Math.exp(-x)); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float start = 0.36787944117f; // 1/e == exp(-1) 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = 1.0f - (float)Math.exp(1.0f - x); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = start + x * (1.0f - start); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 433637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell x *= sViscousFluidNormalize; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return x; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 438c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * Stops the animation. Contrary to {@link #forceFinished(boolean)}, 439c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * aborting the animating cause the scroller to move to the final x and y 440c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * position 4419d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 442c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #forceFinished(boolean) 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void abortAnimation() { 4459d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrX = mFinalX; 4469d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mCurrY = mFinalY; 4479d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = true; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 451c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * Extend the scroll animation. This allows a running animation to scroll 452d663dab7dbefb49877efd2976994fb94cfa4fbd0djken * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}. 4539d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param extend Additional time to scroll in milliseconds. 455c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #setFinalX(int) 456c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #setFinalY(int) 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void extendDuration(int extend) { 4599d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell int passed = timePassed(); 4609d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mDuration = passed + extend; 461d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne mDurationReciprocal = 1.0f / mDuration; 4629d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = false; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 464c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier 465c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier /** 466c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * Returns the time elapsed since the beginning of the scrolling. 4679d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 468c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @return The elapsed time in milliseconds. 469c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier */ 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int timePassed() { 4719d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 473c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier 474c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier /** 475c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * Sets the final position (X) for this scroller. 4769d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 477c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @param newX The new X offset as an absolute distance from the origin. 478c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #extendDuration(int) 479c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #setFinalY(int) 480c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier */ 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFinalX(int newX) { 4829d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalX = newX; 4839d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mDeltaX = mFinalX - mStartX; 4849d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = false; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 487c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier /** 488c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * Sets the final position (Y) for this scroller. 4899d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell * 490c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @param newY The new Y offset as an absolute distance from the origin. 491c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #extendDuration(int) 492c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier * @see #setFinalX(int) 493c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier */ 494c312942b773449f5c6a8a887052aec847ec73b2cCyril Mottier public void setFinalY(int newY) { 4959d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinalY = newY; 4969d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mDeltaY = mFinalY - mStartY; 4979d32d24dbd8a015c9d5c44ed4901d5a666eb8e7fAdam Powell mFinished = false; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 499d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne 500d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne /** 501d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne * @hide 502d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne */ 503d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne public boolean isScrollingInDirection(float xvel, float yvel) { 504d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) && 505d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne Math.signum(yvel) == Math.signum(mFinalY - mStartY); 506d348bb4feff72d047a1037537be2d334a00c380cGilles Debunne } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 508