B4A Library [Lib] Gesture Detector

This library adds the detection of standard gestures (press, single-tap, double-tap, long tap, drag, scroll, fling, pinch, rotation) to B4A. Instead of using the Touch events to figure out what the user really did, now you just set 15 different listeners with one line of code and you get the gestures as events with all the useful values (scrolling distance, fling velocity, pinch variation, rotation angle...).
With this library, you can also know easily the pressure or the size of a touch event.

It works with any view.

Note: you have to create an instance of GestureDetector (with Dim) for each view you want to bind to the detector with SetOnGestureListener.

v2.2:
- Freeware.

v2.3:
- I fixed an issue with the boolean value returned by the OnTouch event with some views (e.g. ListView or ScrollView);
- I added a new demo (GD_SwipeLV);
- The OnDown event is now raised before OnDoubleTap.

v2.4:
- I fixed an issue when a view is dragged after one of the pointer is up (delta values were computed according to the pointer 0, not to the remaining pointer).

Incompatible with Android versions < 2.
 

Attachments

  • GestureDetector v2.4.zip
    35.3 KB · Views: 3,316
  • Java source - GestureDetector.zip
    5.5 KB · Views: 1,355
Last edited:

Informatix

Expert
Licensed User
Longtime User
New version 1.2 (freeware)

I added a return value to the onTouch event. If you set it to True, the event is handled by the view (it's the same behavior as before). If set to False, the event is ignored and passed down to another view under the finger.

New version 2.1 (donationware)

I added a return value to the onTouch event. If you set it to True, the event is handled by the view (it's the same behavior as before). If set to False, the event is ignored and passed down to another view under the finger.

I added two new functions: CreateMotionEvent and PassTouchEventTo. With these new functions, it's now possible to generate touch events or to pass a touch event down to another view in the activity.

I added a demo, GD_Dispatch, to illustrate these new features.
 

NJDude

Expert
Licensed User
Longtime User
Are the Freeware and Donationware libs compatible with each other?, I'm asking this because I see the events are handled differently, for example:

Donationware:
B4X:
gEvent_onTouch(Action As Int, X As Float, Y As Float, MotionEvent As Object)
Freeware:
B4X:
gEvent_onTouch(Action As Int, X As Float, Y As Float, MotionEvent As Object) As Boolean
The app crashes if the user doesn't have the "correct" lib.
 

Informatix

Expert
Licensed User
Longtime User
The two versions (1.2 and 2.1) are compatible and are always compared before release. They have the same onTouch signature. But this signature has been changed in the latest version (I added "As boolean" at the end) so you're probably comparing a former version with a new one.
 

kiki78

Active Member
Licensed User
Longtime User
Hello Informatix,

I try to use "onFling" event (Freeware 1.20 for now).
To discriminate where this event occur on screen, I try to use "getX" method of GestureDetector object with MotionEvent1 parameters.
In example give at post #50, this method take only one parameter, the MotionEvent object. Fine.
But in current version, I need to give ptrIndex.
But to obtain ptrIndex, I use getPointerIndex(ev, PID), and to obtain PID I use getPID(ev, ptrIndex) !
It bites its tail !
How to get out this infernal circle ?
Sorry if my question is trivial, but I certainly miss something...

Regards
 

Informatix

Expert
Licensed User
Longtime User
Hello Informatix,

I try to use "onFling" event (Freeware 1.20 for now).
To discriminate where this event occur on screen, I try to use "getX" method of GestureDetector object with MotionEvent1 parameters.
In example give at post #50, this method take only one parameter, the MotionEvent object. Fine.
But in current version, I need to give ptrIndex.
But to obtain ptrIndex, I use getPointerIndex(ev, PID), and to obtain PID I use getPID(ev, ptrIndex) !
It bites its tail !
How to get out this infernal circle ?
Sorry if my question is trivial, but I certainly miss something...

Regards
0 is the first pointer.
 

kiki78

Active Member
Licensed User
Longtime User
Thank you Informatix,

I have found that first pointer is 0. But if I have multiple point I need to now which one to use.
So my question is why I need to pass ptrIndex to getX method, as it seem's it's embedded in MotionEvent object ?

Regards
 

Informatix

Expert
Licensed User
Longtime User
The motion event contains data for each pointer. So there's a X value for each pointer. How can I return the right value of X if I don't know the pointer?
You get the pointer id and pointer index of each pointer after the first with the event onPointerDown.
Did you look at my Paint example? It shows how to manage many pointers.
 

kiki78

Active Member
Licensed User
Longtime User
So sorry to disturb you...
I expect I obtain one fling event for each pointer, but not test it :oops:.
I will carefully reread your Paint example and make test.
Thank you Informatix for your patience.

Regards
 

b4auser1

Well-Known Member
Licensed User
Longtime User
Hello, Informatix

B4X:
I use
    Private m_clsCheckListAll As ClsCheckList

to show data in

    Dim scvAll As ScrollView
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout(sACTIVITY_NAME)

    m_clsGestureDetector.SetOnGestureListener(scvAll, "Gesture")
  
End Sub

and try to detect left/right swipe using

B4X:
Sub Gesture_onFling(velocityX As Float, velocityY As Float, MotionEvent1 As Object, MotionEvent2 As Object)
Log ("Fling")
Log ("velocityX: " & velocityX)
Log ("velocityY: " & velocityY)
Log ("MotionEvent1: " & MotionEvent1)
Log ("MotionEvent2: " & MotionEvent2)
'    Dim iWidth As Int = m_clsGestureDetector.getX(MotionEvent1, 0) - m_clsGestureDetector.getX(MotionEvent2, 0)
'   
'    If (iWidth) > 100 Then
'        RightSwipe
'    Else If ((iWidth) < -100) Then
'        LeftSwipe
'    End If
   
End Sub

but

MotionEvent1: null

as Log shows:
B4X:
Fling
velocityX: -220.43174743652344
velocityY: -29.126550674438477
MotionEvent1: null
MotionEvent2: MotionEvent { action=ACTION_UP, id[0]=0, x[0]=589.51404, y[0]=760.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x80000000, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=122598, downTime=122293, deviceId=0, source=0x1002 }

How to get MotionEvent1 to be not null ?
 

b4auser1

Well-Known Member
Licensed User
Longtime User
I resolved my problem above, using transparent panel over scvAll
with
B4X:
m_clsGestureDetector.SetOnGestureListener(pnlScvAllGD, "Gesture")
and
B4X:
Sub Gesture_onTouch(Action AsInt, X AsFloat, Y AsFloat, MotionEvent AsObject) AsBoolean
  'Return True 'True = Handle this touch event, False = Ignore it
  Return m_clsGestureDetector.PassTouchEventTo(MotionEvent, scvAll)
End Sub
 
Last edited:

TheMightySwe

Active Member
Licensed User
Longtime User
Hi again,

Do you have a Moneybookers/Skrill account? Just hate to use Cards on the web and I don't have a Paypal account? I like to donate a few $$$ for this library.

/ TMS
 
Top