How to properly make sense of Android's onScroll GestureDetector method?

1.3k views Asked by At

After several StackOverflow posts and Android's onScroll documentation, I am still unable to make sense of how onScroll method works.

Context and What I am trying to achieve: I have a webview with mostly texts in it. I am overriding webview's default scrolling behavior, and instead trying to take control of the scrolling mechanism. I want to be able to -

  1. Scroll by a paragraph length with a fling gesture. I am able to do that by calling Android's onFling method.
  2. Scroll to next sentence with a drag gesture. This is where I am struggling.

From the definition of drag gesture (plus scrolling gesture) in Android, the difference between drag and fling is that, for fling, the user's finger has to leave the surface with a velocity. Having said that, I see that onScroll is called multiple times and onFling only once. I guess that is okay. What I am struggling to understand is what does the parameters do in onScroll method?

I don't quite understand the purpose of event1, event2, distanceX, and distanceY - if all of them change each time onScroll is called. How do you make sense of these parameters? What is the proper way of interpreting them? Android documentation did not help.

UPDATE

I logged my touch movements, and here is how it looks.

Movement: Dragging vertically up without lifting the finger

event 1 X=600.64453, Y=891.5178
event 2 X=594.5489, Y=891.5178
event 1 X=600.64453, Y=886.3
event 2 X=593.7481, Y=886.3
event 1 X=600.64453, Y=879.9082
event 2 X=592.97614, Y=879.9082

Question: Since I moved vertically up, I expect most of my changes in Y axis, and very minimal in X axis. What I see here is that, for event 1, X is always the same, however, Y keeps changing. If event 1 is the first down motion that started the scrolling, shouldn't Y still be the same? But even then, how do you explain why for any pair of {event 1, event 2} here, Xs are different whereas Ys are same? Shouldn't it be the opposite?

Movement: Dragging horizontally from left to right.

event 1 X=340.66406, Y=861.7873
event 2 X=374.05276, Y=861.7873
event 1 X=340.66406, Y=862.9392
event 2 X=382.84317, Y=862.9392
event 1 X=340.66406, Y=864.10034
event 2 X=390.39926, Y=864.10034

Question: Intuition says, movement in horizontal direction should trigger most changes in X axis and minor changes in Y axis. Here, all event 1 Xs are same, but Y is different. Again, I expected both X and Y to be same! For any pair of {event 1, event 2}, Xs are different whereas Ys are same. This sounds normal, but then again, if I look back to the one above, I am getting confused. How do you distinguish them?

Thanks and my apology for a long verbose question!

1

There are 1 answers

4
rhpekarek On

From the docs:

/**
  * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
  * current move {@link MotionEvent}. The distance in x and y is also supplied for
  * convenience.
  *
  * @param e1 The first down motion event that started the scrolling.
  * @param e2 The move motion event that triggered the current onScroll.
  * @param distanceX The distance along the X axis that has been scrolled since the last
  *              call to onScroll. This is NOT the distance between {@code e1}
  *              and {@code e2}.
  * @param distanceY The distance along the Y axis that has been scrolled since the last
  *              call to onScroll. This is NOT the distance between {@code e1}
  *              and {@code e2}.
  * @return true if the event is consumed, else false
  */
  boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);

e1: Since this is the motion event that triggered the scroll, you can expect this to stay the same throughout your scroll.

e2: A user could move their finger around the screen in multiple directions without lifting it and onScroll would be called separately for each change it detects. This is pretty sensitive, so that's why you're seeing onScroll called multiple times.

distanceX and distanceY aren't your total distances traveled, but only the distances since the last time onScroll was called. You can calculate your net distances by comparing the getX() and getY() methods on each MotionEvent.

If all you need to do is check that a scroll was initiated, this is probably more info than you need. You could try and trigger your event only when you receive a unique event1