Advice of Scroller Animation Part I

Advice

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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);
}
}
}

reference articles:

ref1