FlingScroller.java revision b3aab90bb37aa9cc60be32e05678ee55d6575ee8
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.gallery3d.ui; 18 19import com.android.gallery3d.common.Utils; 20 21// This is a customized version of Scroller, with a interface similar to 22// android.widget.Scroller. It does fling only, not scroll. 23// 24// The differences between the this Scroller and the system one are: 25// 26// (1) The velocity does not change because of min/max limit. 27// (2) The duration is different. 28// (3) The deceleration curve is different. 29class FlingScroller { 30 private static final String TAG = "FlingController"; 31 32 // The fling duration (in milliseconds) when velocity is 1 pixel/second 33 private static final float FLING_DURATION_PARAM = 50f; 34 private static final int DECELERATED_FACTOR = 4; 35 36 private int mStartX, mStartY; 37 private int mMinX, mMinY, mMaxX, mMaxY; 38 private double mSinAngle; 39 private double mCosAngle; 40 private int mDuration; 41 private int mDistance; 42 private int mFinalX, mFinalY; 43 44 private int mCurrX, mCurrY; 45 46 public int getFinalX() { 47 return mFinalX; 48 } 49 50 public int getFinalY() { 51 return mFinalY; 52 } 53 54 public int getDuration() { 55 return mDuration; 56 } 57 58 public int getCurrX() { 59 return mCurrX; 60 61 } 62 63 public int getCurrY() { 64 return mCurrY; 65 } 66 67 public void fling(int startX, int startY, int velocityX, int velocityY, 68 int minX, int maxX, int minY, int maxY) { 69 mStartX = startX; 70 mStartY = startY; 71 mMinX = minX; 72 mMinY = minY; 73 mMaxX = maxX; 74 mMaxY = maxY; 75 76 double velocity = Math.hypot(velocityX, velocityY); 77 mSinAngle = velocityY / velocity; 78 mCosAngle = velocityX / velocity; 79 // 80 // The position formula: x(t) = s + (e - s) * (1 - (1 - t / T) ^ d) 81 // velocity formula: v(t) = d * (e - s) * (1 - t / T) ^ (d - 1) / T 82 // Thus, 83 // v0 = d * (e - s) / T => (e - s) = v0 * T / d 84 // 85 86 // Ta = T_ref * (Va / V_ref) ^ (1 / (d - 1)); V_ref = 1 pixel/second; 87 mDuration = (int)Math.round(FLING_DURATION_PARAM 88 * Math.pow(Math.abs(velocity), 1.0 / (DECELERATED_FACTOR - 1))); 89 90 // (e - s) = v0 * T / d 91 mDistance = (int)Math.round( 92 velocity * mDuration / DECELERATED_FACTOR / 1000); 93 94 mFinalX = getX(1.0f); 95 mFinalY = getY(1.0f); 96 } 97 98 public void computeScrollOffset(float progress) { 99 progress = Math.min(progress, 1); 100 float f = 1 - progress; 101 f = 1 - (float) Math.pow(f, DECELERATED_FACTOR); 102 mCurrX = getX(f); 103 mCurrY = getY(f); 104 } 105 106 private int getX(float f) { 107 return (int) Utils.clamp( 108 Math.round(mStartX + f * mDistance * mCosAngle), mMinX, mMaxX); 109 } 110 111 private int getY(float f) { 112 return (int) Utils.clamp( 113 Math.round(mStartY + f * mDistance * mSinAngle), mMinY, mMaxY); 114 } 115} 116