FileDocCategorySizeDatePackage
Scroller.javaAPI DocAndroid 5.1 API20898Thu Mar 12 22:22:10 GMT 2015android.widget

Scroller

public class Scroller extends Object

This class encapsulates scrolling. You can use scrollers ({@link Scroller} or {@link OverScroller}) to collect the data you need to produce a scrolling animation—for example, in response to a fling gesture. Scrollers track scroll offsets for you over time, but they don't automatically apply those positions to your view. It's your responsibility to get and apply new coordinates at a rate that will make the scrolling animation look smooth.

Here is a simple example:

 private Scroller mScroller = new Scroller(context);
...
public void zoomIn() {
// Revert any animation currently in progress
mScroller.forceFinished(true);
// Start scrolling by providing a starting point and
// the distance to travel
mScroller.startScroll(0, 0, 100, 0);
// Invalidate to request a redraw
invalidate();
}

To track the changing positions of the x/y coordinates, use {@link #computeScrollOffset}. The method returns a boolean to indicate whether the scroller is finished. If it isn't, it means that a fling or programmatic pan operation is still in progress. You can use this method to find the current offsets of the x and y coordinates, for example:

if (mScroller.computeScrollOffset()) {
// Get current x and y positions
int currX = mScroller.getCurrX();
int currY = mScroller.getCurrY();
...
}

Fields Summary
private final android.view.animation.Interpolator
mInterpolator
private int
mMode
private int
mStartX
private int
mStartY
private int
mFinalX
private int
mFinalY
private int
mMinX
private int
mMaxX
private int
mMinY
private int
mMaxY
private int
mCurrX
private int
mCurrY
private long
mStartTime
private int
mDuration
private float
mDurationReciprocal
private float
mDeltaX
private float
mDeltaY
private boolean
mFinished
private boolean
mFlywheel
private float
mVelocity
private float
mCurrVelocity
private int
mDistance
private float
mFlingFriction
private static final int
DEFAULT_DURATION
private static final int
SCROLL_MODE
private static final int
FLING_MODE
private static float
DECELERATION_RATE
private static final float
INFLEXION
private static final float
START_TENSION
private static final float
END_TENSION
private static final float
P1
private static final float
P2
private static final int
NB_SAMPLES
private static final float[]
SPLINE_POSITION
private static final float[]
SPLINE_TIME
private float
mDeceleration
private final float
mPpi
private float
mPhysicalCoeff
Constructors Summary
public Scroller(android.content.Context context)
Create a Scroller with the default duration and interpolator.


     
        float x_min = 0.0f;
        float y_min = 0.0f;
        for (int i = 0; i < NB_SAMPLES; i++) {
            final float alpha = (float) i / NB_SAMPLES;

            float x_max = 1.0f;
            float x, tx, coef;
            while (true) {
                x = x_min + (x_max - x_min) / 2.0f;
                coef = 3.0f * x * (1.0f - x);
                tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x;
                if (Math.abs(tx - alpha) < 1E-5) break;
                if (tx > alpha) x_max = x;
                else x_min = x;
            }
            SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x;

            float y_max = 1.0f;
            float y, dy;
            while (true) {
                y = y_min + (y_max - y_min) / 2.0f;
                coef = 3.0f * y * (1.0f - y);
                dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y;
                if (Math.abs(dy - alpha) < 1E-5) break;
                if (dy > alpha) y_max = y;
                else y_min = y;
            }
            SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y;
        }
        SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
    
        this(context, null);
    
public Scroller(android.content.Context context, android.view.animation.Interpolator interpolator)
Create a Scroller with the specified interpolator. If the interpolator is null, the default (viscous) interpolator will be used. "Flywheel" behavior will be in effect for apps targeting Honeycomb or newer.

        this(context, interpolator,
                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
    
public Scroller(android.content.Context context, android.view.animation.Interpolator interpolator, boolean flywheel)
Create a Scroller with the specified interpolator. If the interpolator is null, the default (viscous) interpolator will be used. Specify whether or not to support progressive "flywheel" behavior in flinging.

        mFinished = true;
        if (interpolator == null) {
            mInterpolator = new ViscousFluidInterpolator();
        } else {
            mInterpolator = interpolator;
        }
        mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
        mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
        mFlywheel = flywheel;

        mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
    
Methods Summary
public voidabortAnimation()
Stops the animation. Contrary to {@link #forceFinished(boolean)}, aborting the animating cause the scroller to move to the final x and y position

see
#forceFinished(boolean)

        mCurrX = mFinalX;
        mCurrY = mFinalY;
        mFinished = true;
    
private floatcomputeDeceleration(float friction)

        return SensorManager.GRAVITY_EARTH   // g (m/s^2)
                      * 39.37f               // inch/meter
                      * mPpi                 // pixels per inch
                      * friction;
    
public booleancomputeScrollOffset()
Call this when you want to know the new location. If it returns true, the animation is not yet finished.

        if (mFinished) {
            return false;
        }

        int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
    
        if (timePassed < mDuration) {
            switch (mMode) {
            case SCROLL_MODE:
                final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
                mCurrX = mStartX + Math.round(x * mDeltaX);
                mCurrY = mStartY + Math.round(x * mDeltaY);
                break;
            case FLING_MODE:
                final float t = (float) timePassed / mDuration;
                final int index = (int) (NB_SAMPLES * t);
                float distanceCoef = 1.f;
                float velocityCoef = 0.f;
                if (index < NB_SAMPLES) {
                    final float t_inf = (float) index / NB_SAMPLES;
                    final float t_sup = (float) (index + 1) / NB_SAMPLES;
                    final float d_inf = SPLINE_POSITION[index];
                    final float d_sup = SPLINE_POSITION[index + 1];
                    velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
                    distanceCoef = d_inf + (t - t_inf) * velocityCoef;
                }

                mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
                
                mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
                // Pin to mMinX <= mCurrX <= mMaxX
                mCurrX = Math.min(mCurrX, mMaxX);
                mCurrX = Math.max(mCurrX, mMinX);
                
                mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
                // Pin to mMinY <= mCurrY <= mMaxY
                mCurrY = Math.min(mCurrY, mMaxY);
                mCurrY = Math.max(mCurrY, mMinY);

                if (mCurrX == mFinalX && mCurrY == mFinalY) {
                    mFinished = true;
                }

                break;
            }
        }
        else {
            mCurrX = mFinalX;
            mCurrY = mFinalY;
            mFinished = true;
        }
        return true;
    
public voidextendDuration(int extend)
Extend the scroll animation. This allows a running animation to scroll further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.

param
extend Additional time to scroll in milliseconds.
see
#setFinalX(int)
see
#setFinalY(int)

        int passed = timePassed();
        mDuration = passed + extend;
        mDurationReciprocal = 1.0f / mDuration;
        mFinished = false;
    
public voidfling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY)
Start scrolling based on a fling gesture. The distance travelled will depend on the initial velocity of the fling.

param
startX Starting point of the scroll (X)
param
startY Starting point of the scroll (Y)
param
velocityX Initial velocity of the fling (X) measured in pixels per second.
param
velocityY Initial velocity of the fling (Y) measured in pixels per second
param
minX Minimum X value. The scroller will not scroll past this point.
param
maxX Maximum X value. The scroller will not scroll past this point.
param
minY Minimum Y value. The scroller will not scroll past this point.
param
maxY Maximum Y value. The scroller will not scroll past this point.

        // Continue a scroll or fling in progress
        if (mFlywheel && !mFinished) {
            float oldVel = getCurrVelocity();

            float dx = (float) (mFinalX - mStartX);
            float dy = (float) (mFinalY - mStartY);
            float hyp = FloatMath.sqrt(dx * dx + dy * dy);

            float ndx = dx / hyp;
            float ndy = dy / hyp;

            float oldVelocityX = ndx * oldVel;
            float oldVelocityY = ndy * oldVel;
            if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
                    Math.signum(velocityY) == Math.signum(oldVelocityY)) {
                velocityX += oldVelocityX;
                velocityY += oldVelocityY;
            }
        }

        mMode = FLING_MODE;
        mFinished = false;

        float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
     
        mVelocity = velocity;
        mDuration = getSplineFlingDuration(velocity);
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mStartX = startX;
        mStartY = startY;

        float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
        float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;

        double totalDistance = getSplineFlingDistance(velocity);
        mDistance = (int) (totalDistance * Math.signum(velocity));
        
        mMinX = minX;
        mMaxX = maxX;
        mMinY = minY;
        mMaxY = maxY;

        mFinalX = startX + (int) Math.round(totalDistance * coeffX);
        // Pin to mMinX <= mFinalX <= mMaxX
        mFinalX = Math.min(mFinalX, mMaxX);
        mFinalX = Math.max(mFinalX, mMinX);
        
        mFinalY = startY + (int) Math.round(totalDistance * coeffY);
        // Pin to mMinY <= mFinalY <= mMaxY
        mFinalY = Math.min(mFinalY, mMaxY);
        mFinalY = Math.max(mFinalY, mMinY);
    
public final voidforceFinished(boolean finished)
Force the finished field to a particular value.

param
finished The new finished value.

        mFinished = finished;
    
public floatgetCurrVelocity()
Returns the current velocity.

return
The original velocity less the deceleration. Result may be negative.

        return mMode == FLING_MODE ?
                mCurrVelocity : mVelocity - mDeceleration * timePassed() / 2000.0f;
    
public final intgetCurrX()
Returns the current X offset in the scroll.

return
The new X offset as an absolute distance from the origin.

        return mCurrX;
    
public final intgetCurrY()
Returns the current Y offset in the scroll.

return
The new Y offset as an absolute distance from the origin.

        return mCurrY;
    
public final intgetDuration()
Returns how long the scroll event will take, in milliseconds.

return
The duration of the scroll in milliseconds.

        return mDuration;
    
public final intgetFinalX()
Returns where the scroll will end. Valid only for "fling" scrolls.

return
The final X offset as an absolute distance from the origin.

        return mFinalX;
    
public final intgetFinalY()
Returns where the scroll will end. Valid only for "fling" scrolls.

return
The final Y offset as an absolute distance from the origin.

        return mFinalY;
    
private doublegetSplineDeceleration(float velocity)

        return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
    
private doublegetSplineFlingDistance(float velocity)

        final double l = getSplineDeceleration(velocity);
        final double decelMinusOne = DECELERATION_RATE - 1.0;
        return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
    
private intgetSplineFlingDuration(float velocity)

        final double l = getSplineDeceleration(velocity);
        final double decelMinusOne = DECELERATION_RATE - 1.0;
        return (int) (1000.0 * Math.exp(l / decelMinusOne));
    
public final intgetStartX()
Returns the start X offset in the scroll.

return
The start X offset as an absolute distance from the origin.

        return mStartX;
    
public final intgetStartY()
Returns the start Y offset in the scroll.

return
The start Y offset as an absolute distance from the origin.

        return mStartY;
    
public final booleanisFinished()
Returns whether the scroller has finished scrolling.

return
True if the scroller has finished scrolling, false otherwise.

        return mFinished;
    
public booleanisScrollingInDirection(float xvel, float yvel)

hide

        return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) &&
                Math.signum(yvel) == Math.signum(mFinalY - mStartY);
    
public voidsetFinalX(int newX)
Sets the final position (X) for this scroller.

param
newX The new X offset as an absolute distance from the origin.
see
#extendDuration(int)
see
#setFinalY(int)

        mFinalX = newX;
        mDeltaX = mFinalX - mStartX;
        mFinished = false;
    
public voidsetFinalY(int newY)
Sets the final position (Y) for this scroller.

param
newY The new Y offset as an absolute distance from the origin.
see
#extendDuration(int)
see
#setFinalX(int)

        mFinalY = newY;
        mDeltaY = mFinalY - mStartY;
        mFinished = false;
    
public final voidsetFriction(float friction)
The amount of friction applied to flings. The default value is {@link ViewConfiguration#getScrollFriction}.

param
friction A scalar dimension-less value representing the coefficient of friction.

        mDeceleration = computeDeceleration(friction);
        mFlingFriction = friction;
    
public voidstartScroll(int startX, int startY, int dx, int dy)
Start scrolling by providing a starting point and the distance to travel. The scroll will use the default value of 250 milliseconds for the duration.

param
startX Starting horizontal scroll offset in pixels. Positive numbers will scroll the content to the left.
param
startY Starting vertical scroll offset in pixels. Positive numbers will scroll the content up.
param
dx Horizontal distance to travel. Positive numbers will scroll the content to the left.
param
dy Vertical distance to travel. Positive numbers will scroll the content up.

        startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
    
public voidstartScroll(int startX, int startY, int dx, int dy, int duration)
Start scrolling by providing a starting point, the distance to travel, and the duration of the scroll.

param
startX Starting horizontal scroll offset in pixels. Positive numbers will scroll the content to the left.
param
startY Starting vertical scroll offset in pixels. Positive numbers will scroll the content up.
param
dx Horizontal distance to travel. Positive numbers will scroll the content to the left.
param
dy Vertical distance to travel. Positive numbers will scroll the content up.
param
duration Duration of the scroll in milliseconds.

        mMode = SCROLL_MODE;
        mFinished = false;
        mDuration = duration;
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mStartX = startX;
        mStartY = startY;
        mFinalX = startX + dx;
        mFinalY = startY + dy;
        mDeltaX = dx;
        mDeltaY = dy;
        mDurationReciprocal = 1.0f / (float) mDuration;
    
public inttimePassed()
Returns the time elapsed since the beginning of the scrolling.

return
The elapsed time in milliseconds.

        return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);