Android: Scroller Animation?

Kenn Cal picture Kenn Cal · Mar 31, 2011 · Viewed 22.7k times · Source

I'm a newbie in Android development, and I would just like to know a little bit about the Scroller widget (android.widget.Scroller). How does it animate the view? Can the Animation object, if it exists, be accessed? If so, how? I've read the source code, but could find no clues, or maybe I'm too new?

I just wanted to do some operations after a Scroller finishes scrolling, something like

m_scroller.getAnimation().setAnimationListener(...);

Answer

Bill Phillips picture Bill Phillips · Jun 2, 2011

The Scroller widget doesn't actually do much of the work at all for you. It doesn't fire any callbacks, it doesn't animate anything, it just responds to various method calls.

So what good is it? Well, it does all of the calculation for e.g. a fling for you, which is handy. So what you'd generally do is create a Runnable that repeatedly asks the Scroller, "What should my scroll position be now? Are we done flinging yet?" Then you repost that runnable on a Handler (usually on the View) until the fling is done.

Here's an example from a Fragment I'm working on right now:

private class Flinger implements Runnable {
    private final Scroller scroller;

    private int lastX = 0;

    Flinger() {
        scroller = new Scroller(getActivity());
    }

    void start(int initialVelocity) {
        int initialX = scrollingView.getScrollX();
        int maxX = Integer.MAX_VALUE; // or some appropriate max value in your code
        scroller.fling(initialX, 0, initialVelocity, 0, 0, maxX, 0, 10);
        Log.i(TAG, "starting fling at " + initialX + ", velocity is " + initialVelocity + "");

        lastX = initialX;
        getView().post(this);
    }

    public void run() {
        if (scroller.isFinished()) {
            Log.i(TAG, "scroller is finished, done with fling");
            return;
        }

        boolean more = scroller.computeScrollOffset();
        int x = scroller.getCurrX();
        int diff = lastX - x;
        if (diff != 0) {
            scrollingView.scrollBy(diff, 0);
            lastX = x;
        }

        if (more) {
            getView().post(this);
        }
    }

    boolean isFlinging() {
        return !scroller.isFinished();
    }

    void forceFinished() {
        if (!scroller.isFinished()) {
            scroller.forceFinished(true);
        }
    }
}

The details of using Scroller.startScroll should be similar.