On a Samsung Galaxy Note 10.1 with Android 4.0.4 the GestureDetector
does not fire OnGestureListener#onScroll
when two fingers are placed on screen (it does for one finger). This works well on other devices. In my application I want to enable scrolling only when at least two fingers are involved.
This is the view implementation to reproduce the phenomena:
public class MyView extends View {
GestureDetector scrollGestureDetector;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
scrollGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, final float distanceY) {
System.out.println("SCROLL " + distanceX + ", " + distanceY);
return true;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
scrollGestureDetector.onTouchEvent(event);
return true;
}
}
Is this behavior known/documented/wanted? Are there known workarounds?
onShowPress The user has performed a down MotionEvent and not performed a move or up yet. This event is commonly used to provide visual feedback to the user to let them know that their action has been recognized i.e. highlight an element.
GestureDetector. SimpleOnGestureListener provides an implementation for all of the on<TouchEvent> methods by returning false for all of them. Thus you can override only the methods you care about.
onFling: is that the user lifts his finger in the end of the movement (that is the reason for what onFling is called one time). onScroll: is the general process of moving the viewport (that is, the 'window' of content you're looking at).
Android provides the GestureDetector class for detecting common gestures. Some of the gestures it supports include onDown() , onLongPress() , onFling() , and so on. You can use GestureDetector in conjunction with the onTouchEvent() method described above.
You need to implement one more method onDown
in your GestureDetector.SimpleOnGestureListener
, like this:
scrollGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, final float distanceY) {
System.out.println("SCROLL " + distanceX + ", " + distanceY);
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
});
Because according to this document and this guide:
Notified when a tap occurs with the down MotionEvent that triggered it. This will be triggered immediately for every down event. All other events should be preceded by this.
And
Whether or not you use GestureDetector.OnGestureListener, it's best practice to implement an onDown() method that returns true. This is because all gestures begin with an onDown() message. If you return false from onDown(), as GestureDetector.SimpleOnGestureListener does by default, the system assumes that you want to ignore the rest of the gesture, and the other methods of GestureDetector.OnGestureListener never get called. This has the potential to cause unexpected problems in your app. The only time you should return false from onDown() is if you truly want to ignore an entire gesture.
You need to return true
in onDown
, so that onScroll
will be triggered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With