I've overridden ScrollView
to pass MotionEvent
s to a GestureDetector
to detect fling events on the ScrollView. I need to be able to detect when the scrolling stops. This doesn't coincide with the MotionEvent.ACTION_UP
event because this usually happens at the start of a fling gesture, which is followed by a flurry of onScrollChanged()
calls on the ScrollView.
So basically what we are dealing with here is the following events:
There's no callback for when the onScrollChanged events are done firing. I was thinking of posting a message to the event queue using a Handler
during onFling and waiting for the Runnable
to execute to signal the end of the fling, unfortunately it fires after the first onScrollChanged call.
Any other ideas?
I've combined a few of the answers from here to construct a working listener that resembles the way AbsListView
does it. It's essentially what you describe, and it works well in my testing.
Note: you can simply override ScrollView.fling(int velocityY)
rather than use your own GestureDetector
.
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
public class CustomScrollView extends ScrollView {
private static final int DELAY_MILLIS = 100;
public interface OnFlingListener {
public void onFlingStarted();
public void onFlingStopped();
}
private OnFlingListener mFlingListener;
private Runnable mScrollChecker;
private int mPreviousPosition;
public CustomScrollView(Context context) {
this(context, null, 0);
}
public CustomScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScrollChecker = new Runnable() {
@Override
public void run() {
int position = getScrollY();
if (mPreviousPosition - position == 0) {
mFlingListener.onFlingStopped();
removeCallbacks(mScrollChecker);
} else {
mPreviousPosition = getScrollY();
postDelayed(mScrollChecker, DELAY_MILLIS);
}
}
};
}
@Override
public void fling(int velocityY) {
super.fling(velocityY);
if (mFlingListener != null) {
mFlingListener.onFlingStarted();
post(mScrollChecker);
}
}
public OnFlingListener getOnFlingListener() {
return mFlingListener;
}
public void setOnFlingListener(OnFlingListener mOnFlingListener) {
this.mFlingListener = mOnFlingListener;
}
}